Changeset 90


Ignore:
Timestamp:
07/24/09 09:33:15 (15 years ago)
Author:
ogrimm
Message:
Removed ftdi libraries, streamlined program, slightly expanded command interface
Location:
hvcontrol
Files:
1 added
20 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • hvcontrol/Makefile

    r72 r90  
    33#
    44
    5 SOURCES = hvcontrol.cpp src/CCCommand.cc src/ConsoleCommand.cc src/HV.cc src/HVConfig.cc src/HVCalib.cc src/HVMonitor.cc src/HVStatus.cc src/Log.cc src/ProcessIO.cc src/ReadCard.cc src/Utilities.cc ../pixelmap/Pixel.cc ../pixelmap/PixelMap.cc
    6 
     5SOURCES = hvcontrol.cpp src/HV.cc src/HVConfig.cc src/HVCalib.cc src/ProcessIO.cc ../pixelmap/Pixel.cc ../pixelmap/PixelMap.cc
    76OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
    8 
    97INCDIRS   = -I. -I../pixelmap -I./src
    108
    11 CFLAGS = -pipe -fthread-jumps -funroll-all-loops -O3 -Wall -DOS_LINUX
    12 CPPFLAGS = -pipe -fPIC -fthread-jumps -funroll-all-loops -O3 -Wall -DOS_LINUX $(VMECTRL)
    13 LIBS = -lstdc++ -lz -lpthread -lutil -lfl -lusb -lftdi -L/usr/lib -L/sw/lib
     9CPPFLAGS = -O3 -Wall -DOS_LINUX
     10LIBS = -lstdc++ -lpthread -lfl -lreadline -ltermcap
    1411
    1512hvcontrol: $(OBJECTS)
     
    2522# Implicit rules
    2623
    27 %.o : %.c
    28         $(CC) $(CFLAGS) $(INCDIRS) -c -o $@ $<
    2924%.o : %.cc
    3025        $(CC) $(CPPFLAGS) $(INCDIRS) -c -o $@ $<
  • hvcontrol/hvcontrol.cpp

    r72 r90  
    2121#include <pthread.h>
    2222#include <signal.h>
    23 
    24 #include "ConsoleCommand.h"
    25 #include "CCCommand.h"
     23#include <sys/socket.h>
     24#include <netdb.h>
     25#include <arpa/inet.h>
     26
    2627#include "ProcessIO.h"
    27 #include "HVMonitor.h"
    28 #include "Types.h"
    29 
    30 #define Sleep(x) usleep(x*1000)
    31 
    32 #define DEFAULT_CONFIG "HV.conf"     // Default configuration file
     28
     29#include <readline/readline.h>  // Must be after including ftdi.h!
     30#include <readline/history.h>
     31
     32#define DEFAULT_CONFIG "../config/HV.conf"     // Default configuration file
    3333#define LOCKFILE "/tmp/CTX_HV_LOCK"
    3434
    35 void CrashHandler(int Signal);
    36 
     35// Function prototypes
     36void ConsoleCommand(ProcessIO *);
     37void CCCommand(ProcessIO *);
     38void HVMonitor(ProcessIO *);
     39void SignalHandler(int);
     40void CrashHandler(int);
     41
     42// ================
     43//   Main program
     44// ================
     45//
     46// Several unlikely system call failures are handled via throwing an exception.
    3747
    3848int main(int argc, char *argv[]) {
    3949
    40 
    4150  char config_file[] = DEFAULT_CONFIG, str[MAX_COM_SIZE];
    42 
    43   pthread_t thread_ConsoleCommand; // Read commands from console
    44   pthread_t thread_HVMonitor;      // Reads continuously from HV board(s)
    45   pthread_t thread_CCCommand;      // Thread listening to commands from Central Control
    46 
     51  pthread_t thread_ConsoleCommand,thread_HVMonitor,thread_CCCommand;
    4752  int LockDescriptor;
     53
     54  // Interpret command line (do before lockfile creation in case of exit())
     55  if((argc==3 && strcmp(argv[1],"-c")!=0) || argc==2) {
     56    printf("Usage: %s [-c <ConfigFile>]    Default file is \"%s\"\n", argv[0], DEFAULT_CONFIG);
     57    exit(EXIT_SUCCESS);
     58  }
    4859
    4960  // Assure only one instance of the HV control program runs
    5061  // The flag O_EXCL together with O_CREAT assure that the lock
    5162  // file cannot be opened by another instance, i.e. there are no parallel write accesses
    52   /*  if ((LockDescriptor = open(LOCKFILE,O_RDONLY|O_CREAT|O_EXCL)) == -1) { 
    53     sprintf(str, "Could not create lock file %s", LOCKFILE);
    54     perror(str);
    55     exit(EXIT_FAILURE);
    56   }
    57   close(LockDescriptor);
    58   */
    5963  if((LockDescriptor = open(LOCKFILE,O_WRONLY|O_CREAT|O_EXCL,S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1) {
    6064    if(errno==EEXIST) {
     
    6367      system(str);
    6468    }
    65     else {
    66       sprintf(str, "Could not create lock file %s", LOCKFILE);
    67       perror(str);
    68     }
     69    else printf("Could not create lock file %s (%s)\n", LOCKFILE, strerror(errno));
    6970    exit(EXIT_FAILURE);
    7071  }
     
    7273  sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME>>%s",LOCKFILE,LOCKFILE,LOCKFILE);
    7374  system(str);
    74 
    75 
    76   for (int i=1; i<argc; i++) {
    77     if (argv[i][0] == '-') {
    78       if (argv[i][1] == 'h') {
    79         printf("Usage: %s [-c <ConfigFile>]  default file is \"%s\"\n", argv[0], config_file);
    80         exit(1);
    81       }
    82       if (argv[i][1] == 'c') {
    83         if (argc<i+2) {
    84           printf("Error: missing configuration file after -c option\n");
    85           exit(1);
    86         } else {
    87           sprintf(config_file, "%s", argv[i+1]);
    88         }
    89       }
    90     }
    91   }
    9275 
    9376  system("clear");                   
    94   printf("\n****************** HV Control %s built %s, %s by S. Commichau, updated by S. Stark ******************\n\n",HV_CONTROL_VERSION,__DATE__,__TIME__);
    95 
    96 
    97   // Construct main instance
    98   ProcessIO pio(config_file);
     77  printf("\n*** HV Control built %s, %s (S.Commichau, S.Stark, O.Grimm) ***\n\n",__DATE__,__TIME__);
    9978 
    100  // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls
     79  // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls
    10180  signal(SIGUSR1, &SignalHandler);
    10281  siginterrupt (SIGUSR1, true);
     
    11392  signal(SIGHUP, &CrashHandler);
    11493
     94  // Construct main instance and create mutex for thread synchronization
     95  ProcessIO pio(config_file);
     96  if (pthread_mutex_init(&pio.control_mutex, NULL) != 0) {
     97    perror("pthread_mutex_init failed");
     98    throw;
     99  }
    115100
    116101  // Create threads
    117102  if ((pthread_create(&thread_ConsoleCommand, NULL, (void * (*)(void *)) ConsoleCommand,(void *) &pio)) != 0) {
    118     fprintf(stderr, "pthread_create failed with ConsoleCommand\n");
    119     exit(1);
    120   }
    121 
     103    perror("pthread_create failed with console thread");
     104    throw;
     105  }
    122106  if ((pthread_create(&thread_HVMonitor, NULL, (void * (*)(void *)) HVMonitor,(void *) &pio)) != 0) {
    123     fprintf(stderr, "pthread_create failed with HVMonitor\n");
    124     exit(1);
    125   }
    126 
     107    perror("pthread_create failed with HVMonitor thread");
     108    throw;
     109  }
    127110  if ((pthread_create(&thread_CCCommand, NULL, (void * (*)(void *)) CCCommand,(void *) &pio)) != 0) {
    128     fprintf(stderr, "pthread_create failed with CCCommand\n");
    129     exit(1);
     111    perror("pthread_create failed with socket thread");
     112    throw;
    130113  }
    131114
    132115  // Threads should be accessible for sending signals
    133   pio.status->HVMonitor = thread_HVMonitor;
    134   pio.status->SocketThread = thread_CCCommand;
     116  pio.HVMonitor = thread_HVMonitor;
     117  pio.SocketThread = thread_CCCommand;
    135118
    136119  // Wait for threads to quit
     
    138121  pthread_join(thread_ConsoleCommand, NULL);
    139122  pthread_join(thread_HVMonitor, NULL);
     123
     124  // Destruct mutex and main instance
     125  pthread_mutex_destroy (&pio.control_mutex);
     126  pio.~ProcessIO();
    140127
    141128  // Remove lockfile
     
    146133  }
    147134
    148   return 0;
    149 }
     135  exit(EXIT_SUCCESS);
     136}
     137
     138
     139/********************************************************************\
     140
     141  ConsoleCommand thread
     142
     143  Handle console input using readline library functions to allow
     144  line editing and history capability
     145
     146\********************************************************************/
     147
     148void ConsoleCommand(ProcessIO *m) {
     149
     150  time_t Time;
     151  char Buf[MAX_COM_SIZE], *Command;
     152
     153  while (!m->Exit) {
     154       
     155    // Assemble prompt
     156    snprintf(m->Prompt, sizeof(m->Prompt),"\rHV");
     157    if (m->NumHVBoards == 0) sprintf(m->Prompt+strlen(m->Prompt),"> ");
     158    else {
     159      if (m->FirstChain == m->LastChain) sprintf(m->Prompt+strlen(m->Prompt),"|C%d",m->FirstChain);
     160      else sprintf(m->Prompt+strlen(m->Prompt),"|C%d-%d",m->FirstChain,m->LastChain);
     161
     162      if (m->NumHVBoards == 0) sprintf(m->Prompt+strlen(m->Prompt),"> ");
     163      else if (m->FirstBoard == m->LastBoard) sprintf(m->Prompt+strlen(m->Prompt),"|B%d> ",m->FirstBoard);
     164      else snprintf(m->Prompt,sizeof(m->Prompt),"\rDAQ|B%d-%d> ",m->FirstBoard,m->LastBoard);
     165    }
     166
     167    // Read Command
     168    Command = readline(m->Prompt);
     169    if (Command==NULL) {
     170      m->PrintMessage("Error reading command line input\n");
     171      continue;
     172    }
     173    if(strlen(Command)>0) add_history(Command);
     174
     175    // Log command
     176    strftime(Buf,MAX_COM_SIZE, "%d/%m/%y %X", localtime(&(Time=time(NULL))));
     177    m->PrintMessage(MsgToLog, "CONSOLE(%s)> %s\n", Buf, Command);
     178
     179    // Process command     
     180    pthread_mutex_lock(&m->control_mutex);
     181    m->CommandControl(Command);
     182    pthread_mutex_unlock(&m->control_mutex);
     183         
     184    free(Command);
     185  }
     186}
     187
     188
     189/********************************************************************\
     190
     191  CCCommand thread
     192
     193  Listen to commands from socket (Central Control)
     194 
     195  This thread will block execution in the accept() and read() socket function
     196  while waiting for a connection or data. If the exit function is invoked through
     197  keyboard command, these blocking functions are interrupted by raising the signal
     198  SIGUSR1. Testing on errno=EINTR indicates this termination. The dummy signal
     199  handler below is needed to prevent the standard thread termination occurring
     200  when this signal is received.
     201 
     202\********************************************************************/
     203
     204
     205void CCCommand(ProcessIO *m) {
     206
     207  int ServerSocket,ConnectionSocket,ReadResult;
     208  struct sockaddr_in SocketAddress, ClientAddress;
     209  struct hostent *ClientName;
     210  socklen_t SizeClientAddress=sizeof(ClientAddress);
     211  char Command[MAX_COM_SIZE], Buf[MAX_COM_SIZE];
     212  time_t Time;
     213
     214  // Set up server socket
     215  if ((ServerSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
     216    m->PrintMessage("Could not open server socket, no remote connection possible (%s).\n", strerror(errno));
     217    return;
     218  }
     219
     220  // Allows immediate reuse of socket after closing (circumvents TIME_WAIT)
     221  int Value=1;
     222  if (setsockopt(ServerSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &Value, sizeof (Value)) == -1) {
     223    m->PrintMessage("Warning: Could not set server socket option SO_REUSEADDR (%s)\n", strerror(errno));
     224  }
     225
     226  SocketAddress.sin_family = PF_INET;
     227  SocketAddress.sin_port = htons((unsigned short) m->config->fCCPort);
     228  SocketAddress.sin_addr.s_addr = INADDR_ANY;
     229
     230  if (bind(ServerSocket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1) {
     231    m->PrintMessage("Could not bind port to socket (%s)\n", strerror(errno));
     232    close(ServerSocket);
     233    return;
     234  }
     235  if (listen(ServerSocket, 0) == -1) {
     236    m->PrintMessage("Could not set socket to listening (%s)\n", strerror(errno));
     237    close(ServerSocket);
     238    return;
     239  }
     240 
     241  while (!m->Exit) { // Looping to wait for incoming connection
     242
     243    if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) {
     244      if (errno!=EINTR) m->PrintMessage("Failed to accept incoming connection (%s)\n", strerror(errno));
     245      close(ServerSocket);
     246      return;
     247    }
     248
     249    ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET);
     250    m->PrintMessage("Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown");
     251    m->Socket = ConnectionSocket;
     252
     253    // Looping as long as client exists and program not terminated
     254    while (!m->Exit) {
     255
     256      // Try to read command from socket
     257      memset(Command, 0, sizeof(Command));
     258      ReadResult = read(ConnectionSocket, Command, MAX_COM_SIZE);
     259      if (ReadResult==0) break; // Client does not exist anymore
     260      if (ReadResult==-1) {
     261        if (errno!=EINTR) m->PrintMessage("Error read from socket (%s)\n", strerror(errno));
     262        break;
     263      }
     264      if (Command[strlen(Command)-1]=='\n') Command[strlen(Command)-1]='\0';  // Remove trailing newline
     265     
     266      // Log command
     267      strftime(Buf, MAX_COM_SIZE, "%d/%m/%y %X", localtime(&(Time=time(NULL))));
     268      m->PrintMessage(MsgToConsole|MsgToLog, "SOCKET(%s)> %s\n", Buf, Command);
     269           
     270      // Process command
     271      pthread_mutex_lock(&m->control_mutex);
     272      m->CmdFromSocket = true;
     273      m->CommandControl(Command);
     274      m->CmdFromSocket = false;
     275      pthread_mutex_unlock(&m->control_mutex); 
     276    }
     277
     278    m->Socket = -1;
     279    m->PrintMessage("Disconnected from client.\n");
     280    close(ConnectionSocket);
     281  }
     282  close(ServerSocket);
     283}
     284
     285
     286/********************************************************************\
     287
     288  HVMonitor
     289
     290  Monitor HV board status
     291  Sebastian Commichau, November 2008
     292
     293\********************************************************************/
     294
     295void HVMonitor(ProcessIO *m) {
     296 
     297  while (!m->Exit) {
     298    if (m->state == active) {
     299      pthread_mutex_lock(&m->control_mutex);
     300      m->Monitor();
     301      pthread_mutex_unlock(&m->control_mutex); 
     302    }
     303    usleep((unsigned long)floor(1000000./(m->NumHVBoards*m->fStatusRefreshRate)));
     304  }
     305}
     306
     307
     308/********************************************************************\
     309
     310  Signal handlers
     311
     312\********************************************************************/
    150313
    151314// Remove lock file before running default signal code
     
    156319  raise(Signal);
    157320}
     321
     322// Dummy signal handler to return from blocking syscalls
     323void SignalHandler(int Signal) {
     324  return;         
     325}
  • hvcontrol/src/HV.cc

    r80 r90  
    88
    99  Contents:     Main class for HV supply
    10 
    11   Requirements: Both libftdi and libusb are required for the
    12                 communication - see manual for more details.
    13 
    14                 libftdi: library for talking with FTDI USB <-> Serial
    15                 converter, UM245R.
    16                 http://www.intra2net.com/de/produkte/opensource/ftdi/
    17                
    18                 libusb: library for talking to USB devices from
    19                 user-space. Also needed by libftdi.
    20                 http://libusb.wiki.sourceforge.net/
    2110               
    2211\********************************************************************/
    2312
    24 
    2513#include "HV.h"
    2614
    2715
    28 HV::HV(char** usbdevice, int* usbdevicenumber, FILE* f,bool TestMode): fNumberOfBoards(0) {
    29  
    30   fTestMode = TestMode;
    31 
    32   int i = 0, j = 0, ret = 0;
    33 
    34   char manufacturer[STR_LENGTH], type[STR_LENGTH], serial[STR_LENGTH];
    35 
    36   bzero(manufacturer, sizeof(manufacturer));
    37   bzero(type, sizeof(type));
    38   bzero(serial, sizeof(serial));
    39 
    40   fprintf(stdout,"Scan: ");
    41 
    42   // Search for FTDI devices
    43   for (i = 0;i<MAX_NUM_HVBOARDS;i++)
    44     ftdi_init(&ftdic[i]);
    45 
    46   ftdi_init(&ftdic_dummy);
    47 
    48   if ((i = ftdi_usb_find_all(&ftdic_dummy, &devlist, USB_VENDOR, USB_PRODUCT)) < 0)
    49     fprintf(stderr,"error: ftdi_usb_find_all failed: %d (%s)\n", i, ftdi_get_error_string(&ftdic_dummy));
    50    
    51   fprintf(stdout,"found %d FTDI device(s)\n", i);
    52   i = 0;
    53  
    54   if(fTestMode){
    55     fprintf(stdout,"Test mode: One HVBoard initialized as dummy.\n");
    56     fHVBoard[fNumberOfBoards] = new HVBoard("dummy", 0, &ftdic[fNumberOfBoards],fTestMode);
    57     fNumberOfBoards++;
    58     return;
    59   }
    60   // Obtain information on FTDI devices
    61   for (curdev = devlist; (curdev != NULL && i<MAX_NUM_HVBOARDS); i++) {
    62    
    63     fprintf(stdout,"Device %d:\n", i);
    64    
    65     if ((ret = ftdi_usb_get_strings(&ftdic_dummy, curdev->dev, manufacturer, STR_LENGTH, type, STR_LENGTH, serial, STR_LENGTH)) < 0) {
    66       fprintf(stderr," Error: ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic_dummy));
    67       break;
    68     }
    69 
    70     fprintf(stdout," Manufacturer: %s - Type: %s - Serial: %s\n", manufacturer, type, serial);
    71 
    72     // Fixme: the following code should be revised!
    73     while (j<MAX_NUM_HVBOARDS) {
    74       if (strcmp(serial,usbdevice[j])==0)
    75         break;
    76       j++;
    77     }
    78 
    79     if (j<MAX_NUM_HVBOARDS) {
    80       ret = ftdi_usb_open_desc(&ftdic[fNumberOfBoards], USB_VENDOR, USB_PRODUCT, type, serial);
    81      
    82       // Fixme: this function does not work properly if there is more than one device???!!!
    83       // ret = ftdi_usb_open(&ftdic[fNumberOfBoards], USB_VENDOR, USB_PRODUCT);
    84      
    85       if (ret < 0 && ret != -5)
    86         fprintf(stderr," Error: unable to open FTDI device: %d (%s)\n", i, ftdi_get_error_string(&ftdic[fNumberOfBoards]));
    87       else {
    88        
    89         ftdi_set_baudrate(&ftdic[fNumberOfBoards], USB_BAUDRATE);
    90         ftdi_usb_reset(&ftdic[fNumberOfBoards]);
    91         ftdi_usb_purge_buffers(&ftdic[fNumberOfBoards]);
    92         /*
    93           The FTDI chip keeps data in the internal buffer for a specific
    94           amount of time if the buffer is not full yet to decrease load on the usb bus.
    95         */
    96         ftdi_set_latency_timer(&ftdic[fNumberOfBoards], USB_LATENCY_TIMER);
    97        
    98         fHVBoard[fNumberOfBoards] = new HVBoard(serial, usbdevicenumber[j], &ftdic[fNumberOfBoards],fTestMode);
    99         fNumberOfBoards++;
    100         /*
    101           fprintf(stdout," FTDI open succeeded\n");
    102           fprintf(stdout," Baudrate: %d\n", ftdic[i].baudrate);
    103           fprintf(stdout," USB_read_timeout: %d\n", ftdic[i].usb_read_timeout);
    104           fprintf(stdout," USB_write_timeout: %d\n", ftdic[i].usb_write_timeout);
    105         */
    106       }
    107      
    108     }
    109     else
    110       fprintf(stdout," Warning: found new USB device - check configuration file!\n");
    111 
    112     j=0;   
    113 
    114     curdev = curdev->next;
    115   }
    116 
    117   // Re-order board numbering otherwise it is determined by the connection sequence
    118   ArrangeHVBoards(fHVBoard,fNumberOfBoards);
    119 
    120 }
    121 
    122 
    123 // Bubble-sort HV boards according to board number
    124 void HV::ArrangeHVBoards(HVBoard** fHVBoard, int size) {
    125 
    126   if(fTestMode){
    127     return;
    128   }
    129 
    130   HVBoard* tmp;
    131 
    132   for (int i=size-1;i>0;--i)
    133     for (int pos=0;pos<i;++pos)           
    134       if (fHVBoard[pos]->GetBoardNumber()>fHVBoard[pos+1]->GetBoardNumber()) {
    135         tmp             = fHVBoard[pos];
    136         fHVBoard[pos]   = fHVBoard[pos+1];
    137         fHVBoard[pos+1] = tmp;
    138       }
    139  
    140 }
    141 
    142 
    143 HV::~HV() {
    144 
    145   if(fTestMode){
    146     fprintf(stdout,"Test mode: No FTDI device has to be closed.\n");
    147     return;
    148   }
    149  
    150   int i, ret = 0;
    151  
    152   for (i=0;i<fNumberOfBoards;i++) {
    153     fprintf(stdout,"Device %d: ",i);
    154    
    155     ret = ftdi_usb_close(&ftdic[i]);
    156 
    157     if (ret < 0)
    158       fprintf(stderr, "Unable to close FTDI device: %d (%s)\n", i, ftdi_get_error_string(&ftdic[i]));
    159     else
    160       fprintf(stdout, "FTDI close succeeded\n");
    161 
    162     delete fHVBoard[i];
    163   }
    164  
    165   fprintf(stdout,"FTDI list free\n");
    166   ftdi_list_free(&devlist);
    167 
    168   for (i=0;i<MAX_NUM_HVBOARDS;i++)
    169     ftdi_deinit(&ftdic[i]);
    170 
    171   ftdi_deinit(&ftdic_dummy);
    172 
    173 }
    174 
    175 
    176 HVBoard::HVBoard(char* serial, int number, struct ftdi_context* ftdic,bool TestMode) : fTimeOut(.5)
    177 {
     16// Constructor
     17HVBoard::HVBoard(int DeviceNumber, char *DeviceName, bool TestMode, float TimeOut, bool verbose) {
     18   
     19  char Buffer[BUFFER_LENGTH];
     20  struct termios tio;
    17821 
    17922  fTestMode = TestMode;
    18023  fTestModeWrap = 0;
    181   FTDI_C = ftdic;
    182   sprintf(Serial,"%s",serial);
    183   BoardNumber = number;
    184      
    185 }
    186 
    187 
     24
     25  SetTimeOut(TimeOut);
     26  BoardNumber = DeviceNumber;
     27  BoardName = DeviceName;
     28 
     29  for (int i=0; i<NUM_CHAINS; i++) Overcurrent[i] = false;
     30  ResetButton = false;
     31  WrapOK = true;
     32  LastWrapCount = -1;
     33 
     34  if (fTestMode) {
     35    fDescriptor = 99;
     36    return;
     37  }
     38
     39  ClearVoltageArrays();
     40
     41  // Open device (do not warn on non-existing device)
     42  snprintf(Buffer, BUFFER_LENGTH, "/dev/%s",DeviceName);
     43  if ((fDescriptor = open(Buffer, O_RDWR|O_NOCTTY|O_NDELAY)) == -1) {
     44    if(errno != 2) printf("Error: Could not open device %d/%s (%s)\n", DeviceNumber,DeviceName, strerror(errno));
     45    return;
     46  }
     47
     48  // Get current serial port settings
     49  if (tcgetattr(fDescriptor, &tio) == -1) {
     50    printf("tcgetattr(...) failed (%d/%s)\n", errno, strerror(errno));
     51    return;   
     52  }
     53
     54  // Set baudrate and raw mode
     55  if (cfsetspeed(&tio, BAUDRATE) == -1) printf("Error: Could not set baud rate (%s)\n", strerror(errno));
     56  cfmakeraw(&tio);
     57  if (tcsetattr(fDescriptor, TCSANOW, &tio ) == -1) printf("Errsor with tcsetattr(...) (%s)\n", strerror(errno));
     58
     59  //  Synchronize HV board (if fails, closes device and sets fDescriptor to -2)
     60  unsigned char wbuf = REG_STATUS;
     61  int trial = 0, ret;
     62 
     63  while(++trial<=3) {
     64    if((ret = Communicate(stdout, &wbuf, 1, verbose)) == 1) {
     65      Reset(stdout, verbose);
     66      return;
     67    }
     68    if (ret==0) break;
     69    wbuf = 0;
     70  }
     71  close(fDescriptor);
     72  fDescriptor = -2;
     73  return;
     74}
     75
     76// Destructor (Resetting board)
    18877HVBoard::~HVBoard() {
    189  
    190 }
    191 
    192 
    193 /* For test purposes only - never use this function with a real HV board!!! */
    194 void HVBoard::TestIO() {
    195 
    196   int ret = 0, werrors = 0, rerrors = 0, mismatches = 0;
    197 
    198   unsigned char wbuf[BUFFER_LENGTH], rbuf[BUFFER_LENGTH];
    199 
    200   for (int i=0;i<=0XFF;i++) {
    201    
    202     wbuf[0] = (unsigned char)i;
    203 
    204 #ifdef DO_CAST
    205     ret = ftdi_write_data(FTDI_C,(char*)wbuf,1);
    206 #endif
    207     ret = ftdi_write_data(FTDI_C,wbuf,1);
    208 
    209     if (ret < 0)
    210       werrors++;
    211    
    212 #ifdef DO_CAST
    213     ret = ftdi_read_data(FTDI_C,(char*)rbuf,1);
    214 #endif   
    215     ret = ftdi_write_data(FTDI_C,wbuf,1);   
    216 
    217     if (ret < 0)
    218       rerrors++;
    219    
    220     if (rbuf[0]!=wbuf[0]) {
    221       mismatches++;
    222       fprintf(stdout,"Mismatch - written: 0X%.2X read: 0X%.2X\n",wbuf[0],rbuf[0]);
    223     }
    224   }
    225   fprintf(stdout, "Result: %d write errors, %d read errors, %d mismatches\n",werrors,rerrors,mismatches);
    226 }
    227 
    228 
    229 int HVBoard::Write(unsigned char* data, int size) {
    230   if (fTestMode)
    231     return 3;  // implying that 3 bytes are written
    232 
    233 #ifdef DO_CAST
    234   return ftdi_write_data(FTDI_C, (char*)data, size);
    235 #endif
    236   return ftdi_write_data(FTDI_C, data, size);
    237 }
    238 
    239 
    240 int HVBoard::Read(unsigned char* data, int size) {
    241   if (fTestMode) {
    242     data[0] = fTestModeWrap;
    243     //    fprintf(stdout," Read Data 0X%.2X\n",data[0]);
    244     fTestModeWrap++;
    245     fTestModeWrap = fTestModeWrap%8;
    246     return 1;  // one byte read
    247   }
    248 #ifdef DO_CAST
    249   return ftdi_read_data(FTDI_C, (char*)data, size);
    250 #endif
    251   return ftdi_read_data(FTDI_C, data, size);
    252 }
    253 
    254 
    255 /*
    256  TRead: read from HV Board until fTimeOut has been reached
    257 
    258  Returns:
    259      0 if a read error has occured
    260      1 on success
    261     -1 if fTimeOut [s] has been exceeded
    262 */
    263 int HVBoard::TRead(FILE* fptr, unsigned char* rbuf, bool verbose) {
    264 
    265   if (fTestMode) {
    266     Read(rbuf,BUFFER_LENGTH);
    267     return 1;  // rbuf read
    268   }
    269 
    270   char str[STR_LENGTH];
    271 
    272   long int t1, t2;
    273   int ret = 0;
    274 
    275   t1 = GetMicroSeconds();
    276  
    277   do {
    278    
    279     if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
    280       if (verbose)
    281         if (ret < 0) {
    282           fprintf(stderr, " Read error: %d (%s)\n", ret, ftdi_get_error_string(FTDI_C));
    283           return 0;
    284         }
    285     }
    286     else {
    287 
    288       if (verbose)
    289         fprintf(fptr," %d byte(s) read:\n",ret);
    290      
    291       for (int i=0;i<ret;i++) {
    292         sPrintByteBin(rbuf[i],str);
    293         if (verbose)
    294           fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,rbuf[i]);
    295       }
    296       return 1;
    297     }
    298 
    299     t2 = GetMicroSeconds();
    300 
    301     if ((t2-t1)/1000000. >= fTimeOut) {
    302       fprintf(fptr," Warning: timeout exceeded\n");
    303       return -1;
    304     }
    305 
    306   } while(1);
    307  
     78  if(fDescriptor >= 0 && !fTestMode) {
     79    Reset(stdout, false);
     80    close(fDescriptor);
     81  }
     82}
     83
     84
     85// Communicate: Write and read from HV Board until fTimeOut has been reached
     86//
     87// Returns: 0 read error, 1 success, -1 fTimeOut exceeded
     88int HVBoard::Communicate(FILE* fptr, unsigned char* wbuf, int Bytes, bool verbose) {
     89
     90  unsigned char rbuf;
     91  int ret;
     92  fd_set SelectDescriptor;
     93 
     94  // === Write data ===
     95  if (write(fDescriptor, wbuf, Bytes) < Bytes) {
     96    fprintf(fptr," Error: could not write (all) data to HV board\n");
     97    return 0;
     98  }
     99  if (verbose) {
     100    fprintf(fptr,"%d bytes written:\n", Bytes);
     101    for (int i=0; i<Bytes; i++) fprintf(fptr," Byte %d: %#.2x\n",i,wbuf[i]);
     102  }
     103
     104  // === Try to read until time-out ===
     105  FD_ZERO(&SelectDescriptor);   FD_SET(fDescriptor, &SelectDescriptor);
     106  struct timeval WaitTime = {(long) fTimeOut, (long) ((fTimeOut-(long) fTimeOut)*1e6)};
     107  if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
     108    printf("Error with select() (%d/%s)\n", errno,strerror(errno));
     109    return 0;
     110  }
     111  // Time-out expired?
     112  if (!FD_ISSET(fDescriptor, &SelectDescriptor)) {
     113    if (verbose) printf("Time-out of %.2f seconds expired while reading\n", fTimeOut);
     114    return -1;
     115  }
     116  // Read error?   
     117  if ((ret = read(fDescriptor, &rbuf, 1)) == -1) {
     118    fprintf(stderr, " Read error (%s)\n", strerror(errno));
     119    return 0;
     120  }
     121
     122  // === Update status information ===
     123  if (LastWrapCount != -1) {
     124    if ((LastWrapCount+1)%8 == (rbuf & 0X07)) WrapOK = true;
     125    else WrapOK = false;
     126  }
     127  LastWrapCount = rbuf & 0X07; 
     128  for (int i=0; i<NUM_CHAINS; i++) Overcurrent[i]=(rbuf & (0X08 << i));
     129  ResetButton = (bool) (rbuf & 0X80);
     130
     131  if (verbose && ret==1) fprintf(fptr," 1 byte read: %#.2x\n", rbuf); 
     132 
     133  return 1;
    308134}
    309135
    310136
    311137/* Reset HV board - uses TRead() and has same return values */
    312 int HVBoard::Reset(FILE* fptr, unsigned char* rbuf, bool verbose) {
    313 
    314   if (fTestMode)
    315     return 1;
    316 
    317   char str[STR_LENGTH];
     138int HVBoard::Reset(FILE* fptr, bool verbose) {
     139 
     140  if (fTestMode) return 1;
    318141
    319142  unsigned char wbuf[] = {REG_RESET,0,0};
    320  
    321   if (Write(wbuf,3) < 1) {
    322     fprintf(fptr," Error: could not write to HV board\n");
    323     return 0;
    324   }
    325  
    326   if (verbose)
    327     fprintf(fptr," 3 bytes written:\n");
    328  
    329   for (int i=0;i<3;i++) {
    330     sPrintByteBin(wbuf[i],str);
    331     if (verbose)
    332       fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
    333   }
    334 
    335   return TRead(fptr,rbuf,verbose);
    336 
     143  int ret;
     144 
     145  if((ret = Communicate(fptr, wbuf, 3, verbose)) == 1) ClearVoltageArrays(); 
     146  return ret;
    337147}
    338148
    339149
    340150/* Read status register - uses TRead() and has same return values */
    341 int HVBoard::GetStatus(FILE* fptr, unsigned char* rbuf, bool verbose) {
    342   if (fTestMode){
    343     //    printf("Test mode. (Get Status) \n");
    344     return TRead(fptr,rbuf,verbose);
    345     return 1;
    346   }
    347 
    348   char str[STR_LENGTH];
     151int HVBoard::GetStatus(FILE* fptr, bool verbose) {
     152
     153  if (fTestMode) return 1;
    349154
    350155  unsigned char wbuf[] = {REG_STATUS,0,0};
    351156 
    352   if (Write(wbuf,3) < 1) {
    353     if (verbose)
    354       fprintf(fptr," Error: could not write to HV board\n");
    355     return 0;
    356   }
    357 
    358   if (verbose)
    359     fprintf(fptr," 3 bytes written:\n");
    360  
    361   for (int i=0;i<3;i++) {
    362     sPrintByteBin(wbuf[i],str);
    363     if (verbose)
    364       fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
    365   }
    366  
    367   return TRead(fptr,rbuf,verbose);
    368 
     157  return Communicate(fptr, wbuf, 3, verbose);
    369158}
    370159
    371160
    372161/* Set high voltage - uses TRead() and has same return values */
    373 int HVBoard::SetHV(FILE* fptr, int chain, unsigned int channel, unsigned int hv, unsigned char* rbuf, bool verbose) {
     162int HVBoard::SetHV(FILE* fptr, int chain, unsigned int channel, unsigned int hv, bool verbose) {
    374163
    375164  if (fTestMode){
     
    377166    return 1;
    378167  }
    379 
    380  
    381   char str[STR_LENGTH];
    382 
     168 
    383169  unsigned char wbuf[] = {0,0,0};
    384170
    385   if (!(hv>=0.0 && hv<=0X3FFF)) {
     171  if (!(hv>=0 && hv<=0x3FFF)) {
    386172    fprintf(fptr," Error: HV beyond limits [0 - 0x3FFF]\n");
    387173    return 0;
    388174  }
    389175 
    390 
    391176  switch (chain) {
    392    
    393   case 0: wbuf[0] = REG_HV0; break;
    394   case 1: wbuf[0] = REG_HV1; break;
    395   case 2: wbuf[0] = REG_HV2; break;
    396   case 3: wbuf[0] = REG_HV3; break;
    397 
    398   default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0;
    399 
     177    case 0: wbuf[0] = REG_HV0; break;
     178    case 1: wbuf[0] = REG_HV1; break;
     179    case 2: wbuf[0] = REG_HV2; break;
     180    case 3: wbuf[0] = REG_HV3; break;
     181
     182    default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0;
    400183  }
    401184 
     
    406189  wbuf[2] |= (unsigned char)(hv & 0X000000FF);              // Add [D7-D0]
    407190   
    408 
    409   if (Write(wbuf,3) < 1) {
    410     fprintf(fptr," Error: could not write to HV board\n");
    411     return 0;
    412   }
    413 
    414   if (verbose)
    415     fprintf(fptr," 3 bytes written:\n");
    416 
    417   for (int i=0;i<3;i++) {
    418     sPrintByteBin(wbuf[i],str);
    419     if (verbose)
    420       fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
    421   }
    422 
    423   return TRead(fptr,rbuf,verbose);
    424  
    425 }
    426 
    427 
    428 /* Set reference voltage - uses TRead() and has same return values */
    429 int HVBoard::SetVRef(FILE* fptr, int chain, unsigned int vref, unsigned char* rbuf, bool verbose) {
    430 
    431     if (fTestMode){
    432     printf("Test mode. Nothing to be done.\n");
    433     return 1;
    434   }
    435 
    436   char str[STR_LENGTH];
    437 
    438   unsigned char wbuf[] = {0,0,0};
    439  
    440   if (!(vref>=0 && vref<=0X3FFF)) {
    441     if (verbose)
    442       fprintf(fptr," Error: vref beyond limits\n");
    443     return 0;
    444   }
    445 
    446   switch (chain) {
    447 
    448   case 0: wbuf[0] = REG_VREF0; break;
    449   case 1: wbuf[0] = REG_VREF1; break;
    450   case 2: wbuf[0] = REG_VREF2; break;
    451   case 3: wbuf[0] = REG_VREF3; break;
    452 
    453   default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0;
    454 
    455   }
    456  
    457   // Assemble bytes
    458   wbuf[0] |= (unsigned char)((vref >> 13) & 0X0000000F); // Add [D13]
    459   wbuf[1] |= (unsigned char)((vref >> 5)  & 0X000000FF); // Add [D12-D5]
    460   wbuf[2] |= (unsigned char)((vref << 3)  & 0X000000FF); // Add [D4-D0]
    461    
    462   // PD bits (device clear) are not used
    463   wbuf[0] &= ~REG_PD1;
    464   wbuf[0] &= ~REG_PD2;
    465 
    466   if (Write(wbuf,3) < 1) {
    467     fprintf(fptr," Error: could not write to HV board\n");
    468     return 0;
    469   }
    470 
    471   if (verbose)
    472     fprintf(fptr," 3 bytes written:\n");
    473 
    474   for (int i=0;i<3;i++) {
    475     sPrintByteBin(wbuf[i],str);
    476     if (verbose)
    477       fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
    478   }
    479 
    480   return TRead(fptr,rbuf,verbose);
    481  
    482 }
    483 
    484 
    485 /*
    486  Init: initialize (synchronize) HV board - to be used before any other access!
    487 
    488  Returns 0 if an error has occured, 1 on success.
    489 
    490  Before any other access the HV board communication has to be synchronized.
    491  Each write access requires three bytes to be sent from the computer to the
    492  HV board. The HV board sends back one byte containing status information.
    493 
    494  The normal initialization procedure would be the following:
    495 
    496  1.   send one byte (0X80 = REG_STATUS).
    497  1.1. try reading as long as fTimeOut is not exceeded.
    498 
    499  2.   send again one byte (0X00).
    500  2.1. try reading as long as fTimeOut is not exceeded.
    501 
    502  3.   send again one byte (0X00).
    503  3.1. try reading again as long as fTimeOut is not exceeded.
    504  
    505  Note: from time to time there are problems when performing only 3 trials! Reason:
    506  the first byte written by libftdi can get lost somewhere between
    507  libusb <-> kernel <-> FTDI chip. I haven't found yet any solution to this.
    508  To solve the issue, another byte is sent to assure a proper synchronization,
    509  even though the first byte was lost:
    510 
    511  4.   send again one byte (0X00).
    512  4.1. try reading again as long as fTimeOut is not exceeded; if fTimeOut
    513       has been exceeded return.
    514 
    515  See also: http://lists.omnipotent.net/pipermail/lcdproc/2008-June/012235.html
    516 */
    517 int HVBoard::Init(bool verbose) {
    518 
    519 
    520   unsigned char wbuf = REG_STATUS;
    521   unsigned char rbuf[STR_LENGTH];
    522  
    523   int trial = 1;
    524   int ret = 0;
    525 
    526   long int t1, t2;
    527 
    528 
    529   // First send 0X80
    530   if (Write(&wbuf,1) < 1) {
    531     if (verbose)
    532       fprintf(stdout," Error: could not write to HV board\n");
    533     return 0;
    534   }
    535   else
    536     if (verbose)
    537       fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
    538  
    539 
    540   t1 = GetMicroSeconds();
    541 
    542 
    543   // Read - first trial
    544   do {
    545 
    546     t2 = GetMicroSeconds();
    547    
    548     if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
    549       if (verbose)
    550         if (ret < 0) {
    551           fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
    552           return 0;
    553         }
     191  return Communicate(fptr, wbuf, 3, verbose);
     192}
     193
     194
     195// Set all voltages of board to zero
     196void HVBoard::ClearVoltageArrays() {
     197
     198  for (int j=0; j<NUM_CHAINS; j++) {
     199    for (int k=0; k<NUM_CHANNELS; k++){
     200      HV[j][k] = 0;
     201      HVV[j][k] = 0.0;
    554202    }
    555     else {
    556       if (verbose)
    557         fprintf(stdout," %d byte(s) read:",ret);
    558       for (int i=0;i<ret;i++)
    559         if (verbose)
    560           fprintf(stdout," 0X%.2X",rbuf[i]);
    561       if (verbose)
    562         fprintf(stdout,"\n");
    563       fprintf(stdout," Success: initialization done (%d trial)\n",trial);
    564       return 1;
    565     }
    566    
    567     if ((t2-t1)/1000000. > fTimeOut) {
    568       if (verbose)
    569         fprintf(stdout," Warning: timeout exceeded\n");
    570       trial++;
    571      
    572       // Second write
    573       wbuf = 0;
    574       if (Write(&wbuf,1) < 1) {
    575         if (verbose)
    576           fprintf(stdout," Error: could not write to HV board\n");
    577         return 0;
    578       }
    579       else
    580         if (verbose)
    581           fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
    582      
    583       t1 = GetMicroSeconds();
    584      
    585       // Read - second trial
    586       do {
    587 
    588         t2 = GetMicroSeconds();
    589    
    590         if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
    591           if (verbose)
    592             if (ret < 0) {
    593               fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
    594               return 0;
    595             }
    596         }
    597         else {
    598           if (verbose)
    599             fprintf(stdout," %d byte(s) read:",ret);
    600           for (int i=0;i<ret;i++)
    601             if (verbose)
    602               fprintf(stdout," 0X%.2X",rbuf[i]);
    603           if (verbose)
    604             fprintf(stdout,"\n");
    605           fprintf(stdout," Success: initialization done (%d trials)\n",trial);
    606           return 1;
    607         }
    608 
    609         if ((t2-t1)/1000000. > fTimeOut) {
    610           if (verbose)
    611             fprintf(stdout," Warning: timeout exceeded\n");
    612           trial++;
    613          
    614           // Third write
    615           wbuf = 0;
    616           if (Write(&wbuf,1) < 1) {
    617             if (verbose)
    618               fprintf(stdout," Error: could not write to HV board\n");
    619             return 0;
    620           }
    621           else
    622             if (verbose)
    623               fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
    624 
    625 
    626           // Read - third trial
    627           do {
    628            
    629             t2 = GetMicroSeconds();
    630            
    631             if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
    632               if (verbose)
    633                 if (ret < 0) {
    634                   fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
    635                   return 0;
    636                 }
    637             }
    638             else {
    639               if (verbose)
    640                 fprintf(stdout," %d byte(s) read:",ret);
    641               for (int i=0;i<ret;i++)
    642                 if (verbose)
    643                   fprintf(stdout," 0X%.2X",rbuf[i]);
    644               if (verbose)
    645                 fprintf(stdout,"\n");
    646               fprintf(stdout," Success: initialization done (%d trials)\n",trial);
    647               return 1;
    648             }
    649            
    650            
    651             if ((t2-t1)/1000000. > fTimeOut) {
    652               if (verbose)
    653                 fprintf(stdout," Warning: timeout exceeded\n");
    654               trial++;
    655              
    656               // Fourth write
    657               wbuf = 0;
    658               if (Write(&wbuf,1) < 1) {
    659                 if (verbose)
    660                   fprintf(stdout," Error: could not write to HV board\n");
    661                 return 0;
    662               }
    663               else
    664                 if (verbose)
    665                   fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
    666            
    667              
    668               // Read - fourth and last trial
    669               do {
    670                
    671                 t2 = GetMicroSeconds();
    672                
    673                 if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
    674                   if (verbose)
    675                     if (ret < 0) {
    676                       fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
    677                       return 0;
    678                     }
    679                 }
    680                 else {
    681                   if (verbose)
    682                     fprintf(stdout," %d byte(s) read:",ret);
    683                   for (int i=0;i<ret;i++)
    684                     if (verbose)
    685                       fprintf(stdout," 0X%.2X",rbuf[i]);
    686                   if (verbose)
    687                     fprintf(stdout,"\n");
    688                   fprintf(stdout," Success: initialization done (%d trials)\n",trial);
    689                   return 1;
    690                 }
    691                                
    692                 if ((t2-t1)/1000000. > fTimeOut) {
    693                   if (verbose)
    694                     fprintf(stdout," Error: timeout exceeded - initialization failed (%d trials)\n",trial);
    695                   return 0;
    696                  
    697                 }
    698                
    699               } while (1);
    700                      
    701             }
    702                    
    703           } while (1);
    704 
    705         }
    706 
    707       } while (1);
    708            
    709     }
    710 
    711   } while (1);
    712 
    713 
    714   return 0;
    715 }
    716 
    717 
    718 /* Decode wrap counter */
    719 int HVBoard::DecodeWrap(unsigned char* rbuf) {
    720 
    721   return (*rbuf & 0X07);
    722 
    723 }
    724 
    725 
    726 /* Decode over current bits */
    727 void HVBoard::DecodeOC(bool OC[], unsigned char* rbuf) {
    728 
    729   for (int i=0;i<MAX_NUM_CHAINS;i++)
    730     OC[i]=(*rbuf & (0X08 << i));
    731 }
    732 
    733 
    734 /* Decode bit indicating manual reset */
    735 bool HVBoard::DecodeReset(unsigned char* rbuf) {
    736 
    737   return (bool)(*rbuf & 0X80);
    738 
    739 }
    740 
    741 
     203  }
     204}
     205
     206
     207// Set time-out to wait for read
     208void HVBoard::SetTimeOut(double t) {
     209
     210  if (t >= MIN_TIMEOUT && t <= MAX_TIMEOUT) fTimeOut  = t;
     211  else fTimeOut  = 1.0;
     212}
  • hvcontrol/src/HV.h

    r80 r90  
    22#define HV_H_SEEN
    33
    4 #include "Types.h"
    5 #include "Utilities.h"
    6 
    7 #include <ftdi.h>
     4#include <termios.h>            // POSIX terminal control definitions
     5#include <fcntl.h>              // File control definitions => fcntl() in fcn OpenPort()
     6#include <errno.h>
     7#include <stdio.h>
     8#include <unistd.h>
    89#include <sys/ioctl.h>
    910
     11#include <HVConfig.h>
    1012
    11 #ifndef NULL
    12 #ifdef __cplusplus
    13 #define NULL 0
    14 #else
    15 #define NULL ((void *)0)
    16 #endif
    17 #endif
    18 
    19 
    20 // Have a look at http://www.linux-usb.org/usb.ids
    21 // Vendor: Future Technology Devices International, Ltd (FTDI)
    22 #define USB_VENDOR  0X0403
    23 // Product: FT232 USB-Serial (UART) IC (USB <-> Serial converter, UM245R)
    24 #define USB_PRODUCT 0X6001
    25 
    26 
    27 #define USB_BAUDRATE 115000
    28 #define USB_LATENCY_TIMER 1
    29 
     13#define BAUDRATE B115200
    3014
    3115// HV board control registers
    32 #define REG_VREF0   0X00
    33 #define REG_VREF1   0X08
    34 #define REG_VREF2   0X10
    35 #define REG_VREF3   0X18
    36 
    3716#define REG_HV0     0X20
    3817#define REG_HV1     0X28
     
    4221#define REG_RESET   0XF8
    4322#define REG_STATUS  0X80
    44 
    45 #define REG_PD1     0X04
    46 #define REG_PD2     0X02
    47 
    4823
    4924// HV board status bits
     
    5833class HVBoard {
    5934 
    60  public:
    61  
    62   HVBoard(char* serial, int number, struct ftdi_context* ftdic, bool TestMode);
    63   ~HVBoard();
    64 
    65   bool fTestMode;
    66 
    67   int Init(bool verbose);
    68   int Reset(FILE* fptr, unsigned char* rbuf, bool verbose);
    69   int GetStatus(FILE* fptr, unsigned char* rbuf, bool verbose);
    70   int SetVRef(FILE* fptr, int chain, unsigned int vref, unsigned char* rbuf, bool verbose);
    71   int SetHV(FILE* fptr, int chain, unsigned int channel, unsigned int hv, unsigned char* rbuf, bool verbose);
    72   struct ftdi_context* GetFTDI_C() {return FTDI_C;}
    73   char* GetSerial() {return Serial;}
    74   int GetBoardNumber() {return BoardNumber;}
    75   int Write(unsigned char* data, int size);
    76   int Read(unsigned char* data, int size);
    77   int TRead(FILE* fptr, unsigned char* rbuf, bool verbose);
    78   void SetTimeOut(float t) {fTimeOut = t;}
    79   float GetTimeOut() {return fTimeOut;}
    80   void TestIO();       // Warning: NEVER use this function with a real HV board!!!
    81   int DecodeWrap(unsigned char* rbuf);
    82   void DecodeOC(bool OC[], unsigned char* rbuf);
    83   bool DecodeReset(unsigned char* rbuf);
    84 
    85   struct ftdi_context* FTDI_C;
    86   char Serial[STR_LENGTH];
    87   int  BoardNumber;
    88   float fTimeOut;      // [s] timeout to return from read
    89   int fTestModeWrap;
    90  
    91 };
    92 
    93 
    94 
    95 class HV {
     35   int BoardNumber;
     36   int fTestModeWrap;
     37   bool fTestMode;
    9638
    9739 public:
    9840 
    99   HV(char** usbdevice, int* usbdevicenumber, FILE* f,bool TestMode);
    100   ~HV();
     41   HVBoard(int, char *, bool, float, bool);
     42   ~HVBoard();
    10143
    102   int fNumberOfBoards;
    103   int fMaxNumberOfBoards;
     44   int fDescriptor;
     45   bool Overcurrent[NUM_CHAINS];
     46   bool ResetButton;
     47   bool WrapOK;
     48   int LastWrapCount;
     49   double fTimeOut;      // [s] timeout to return from read
     50 
     51   char *BoardName;
     52   int HV[NUM_CHAINS][NUM_CHANNELS];      // HV value in DAC units
     53   double HVV[NUM_CHAINS][NUM_CHANNELS];  // HV value in volts
    10454
    105   bool fTestMode;
    106 
    107   HVBoard* fHVBoard[MAX_NUM_HVBOARDS];
    108   int GetNumberOfBoards() {return fNumberOfBoards;}
    109   void SetNumberOfBoards(int i) {fNumberOfBoards = i;}
    110   HVBoard* GetHVBoard(int i) {return fHVBoard[i];}
    111  
    112  protected:
    113 
    114   // For FTDI USB <-> serial converter
    115   struct ftdi_context ftdic[MAX_NUM_HVBOARDS];
    116   struct ftdi_context ftdic_dummy;
    117   struct ftdi_device_list *devlist, *curdev;
    118  
    119   void ArrangeHVBoards(HVBoard** fHVBoard, int size);
    120  
     55   void ClearVoltageArrays();
     56   int Reset(FILE*, bool);
     57   int GetStatus(FILE*, bool);
     58   int SetHV(FILE*, int, unsigned int, unsigned int, bool);
     59   int GetBoardNumber() {return BoardNumber;}
     60   int Communicate(FILE*, unsigned char*, int, bool);
     61   void SetTimeOut(double);
    12162};
    12263
  • hvcontrol/src/HVCalib.cc

    r46 r90  
    1212
    1313
    14 #include "HVCalib.h"
    1514#include <stdio.h>
    1615#include <iostream>
    1716#include <fstream>
    1817#include <math.h>
     18
     19#include "HVCalib.h"
     20
    1921using namespace std;
    20 
    21 
    22 
    2322
    2423
     
    3938
    4039
    41   HVArray = new float***[hvConfig->NumHVBoards];
     40  HVArray = new double***[hvConfig->NumHVBoards];
    4241  for(int i=0; i<hvConfig->NumHVBoards; i++) {
    43     HVArray[i] = new float**[NCHAIN];
    44     for(int j=0; j<NCHAIN; j++) {
    45       HVArray[i][j] = new float*[NCHANNEL];
    46       for(int k=0; k<NCHANNEL; k++) {
    47         HVArray[i][j][k] = new float[NDACValues];
     42    HVArray[i] = new double**[NUM_CHAINS];
     43    for(int j=0; j<NUM_CHAINS; j++) {
     44      HVArray[i][j] = new double*[NUM_CHANNELS];
     45      for(int k=0; k<NUM_CHANNELS; k++) {
     46        HVArray[i][j][k] = new double[NDACValues];
    4847      }
    4948    }
     
    5251  DACArray = new int***[hvConfig->NumHVBoards];
    5352  for(int i=0; i<hvConfig->NumHVBoards; i++) {
    54     DACArray[i] = new int**[NCHAIN];
    55     for(int j=0; j<NCHAIN; j++) {
    56       DACArray[i][j] = new int*[NCHANNEL];
    57       for(int k=0; k<NCHANNEL; k++) {
     53    DACArray[i] = new int**[NUM_CHAINS];
     54    for(int j=0; j<NUM_CHAINS; j++) {
     55      DACArray[i][j] = new int*[NUM_CHANNELS];
     56      for(int k=0; k<NUM_CHANNELS; k++) {
    5857        DACArray[i][j][k] = new int[NHVValues];
    5958      }
     
    6160  }
    6261
    63 
    64 
    6562  for(int i=0; i<hvConfig->NumHVBoards; i++){
    66   //  for(int i=0; i<1; i++){
    67     for(int j=0;j<NCHAIN;j++){
    68       //for(int j=0;j<1;j++){
     63    for(int j=0; j<NUM_CHAINS; j++){
    6964      sprintf(calibfile,"Calib/%s_%c%d.txt",hvConfig->fUSBDevice[i],65+j,1);
    70       //      printf("Calibration tabel 0: %s\n", calibfile);
    7165      ifstream fin(calibfile);
    7266
     
    7468        fin >> dac;
    7569        idacOld = 0;
    76         if ((int)dac >= hvConfig->DACMin) {
     70        if ((int) dac >= hvConfig->DACMin) {
    7771          if (first){
    78             iDACMin = (int)dac;
     72            iDACMin = (int) dac;
    7973            first = false;
    8074          }
    8175          idac = (int)dac - iDACMin;
    8276          istep = idac - idacOld;
    83           for(int k=0;k<NCHANNEL;k++){
     77          for(int k=0; k<NUM_CHANNELS; k++){
    8478            fin>>HVArray[i][j][k][idac];
    8579            for (int l=1; l<istep;l++){
     
    10094
    10195  for(int i=0; i<hvConfig->NumHVBoards; i++){
    102     //  for(int i=0; i<1; i++){
    103     for(int j=0;j<NCHAIN;j++){
    104       //  for(int j=0;j<1;j++){
    105       for(int k=0;k<NCHANNEL;k++){
    106         //for(int k=0;k<1;k++){
     96    for(int j=0;j<NUM_CHAINS;j++){
     97      for(int k=0;k<NUM_CHANNELS;k++){
    10798        ihvOld = 0;
    10899        first = true;
     
    117108            ihv1000 = (int)((hv1000>=0)?ceil(hv1000):floor(hv1000));
    118109          }
    119           else {
    120             ihv1000 = (int)((hv1000<0)?ceil(hv1000):floor(hv1000));
    121           }
    122           if (ihv1000 <= ihvOld){
    123             continue;
    124           }
     110          else ihv1000 = (int)((hv1000<0)?ceil(hv1000):floor(hv1000));
     111
     112          if (ihv1000 <= ihvOld) continue;
    125113          else if (ihv1000 > ihvOld){
    126             for (int m=0; m<(ihv1000-ihvOld);m++){
     114            for (int m=0; m<(ihv1000-ihvOld); m++){
    127115              DACArray[i][j][k][ihvOld+m] = l+iDACMin;
    128116              //printf("HV = %d, HVArr = %f, DACArray = %d, m = %d. \n",ihvOld+m,HVArray[i][j][k][l],DACArray[i][j][k][ihvOld+m],m);
     
    143131
    144132  for (int i=0; i<MAX_NUM_HVBOARDS; i++){
    145     for (int j=0; j<NCHAIN;j++){
    146       for (int k=0; k<NCHANNEL;k++){
     133    for (int j=0; j<NUM_CHAINS;j++){
     134      for (int k=0; k<NUM_CHANNELS;k++){
    147135        delete [] HVArray[i][j][k];
    148136        delete [] HVArray;
     
    152140
    153141  for (int i=0; i<MAX_NUM_HVBOARDS; i++){
    154     for (int j=0; j<NCHAIN;j++){
    155       for (int k=0; k<NCHANNEL;k++){
     142    for (int j=0; j<NUM_CHAINS;j++){
     143      for (int k=0; k<NUM_CHANNELS;k++){
    156144        delete [] DACArray[i][j][k];
    157145        delete [] DACArray;
     
    163151/////////////////////////////////////////////////////////////////////////
    164152
    165 float HVCalib::DACToHV(int dac, int board, int chain, int channel) {
     153double HVCalib::DACToHV(int dac, int board, int chain, int channel) {
    166154  if (dac < iDACMin){
    167155    return HVArray[board][chain][channel][0] + (dac - iDACMin)*fHVCalibSlope;
     
    173161/////////////////////////////////////////////////////////////////////////
    174162
    175 int HVCalib::HVToDAC(float hv, int board, int chain, int channel) {
     163int HVCalib::HVToDAC(double hv, int board, int chain, int channel) {
    176164  if (hv < HVArray[board][chain][channel][0]){
    177165        return iDACMin + (int)((hv - HVArray[board][chain][channel][0])/fHVCalibSlope);
     
    180168    int ihv = 0;
    181169    double intpart;
    182     float hv1000 = (hv-HVArray[board][chain][channel][0])*1000.;
     170    double hv1000 = (hv-HVArray[board][chain][channel][0])*1000.;
    183171    if (modf(hv1000,&intpart) >= 0.5){
    184       ihv = (int)((hv1000>=0)?ceil(hv1000):floor(hv1000));
     172      ihv = (int) (hv1000>=0 ? ceil(hv1000) : floor(hv1000));
    185173    }
    186174    else {
    187       ihv = (int)((hv1000<0)?ceil(hv1000):floor(hv1000));
     175      ihv = (int) (hv1000<0 ? ceil(hv1000) : floor(hv1000));
    188176    }
    189177    return DACArray[board][chain][channel][ihv];
  • hvcontrol/src/HVCalib.h

    r40 r90  
    1 
    21#ifndef HVCALIB_H_SEEN
    32#define HVCALIB_H_SEEN
    43
     4#include <string.h>
    55
    6 #include <string.h>
    7 #include <HVConfig.h>
    8 #include "Types.h"
    9 
    10 #define NCHAIN 4
    11 #define NCHANNEL 32
     6#include "HVConfig.h"
    127
    138
    149class HVCalib {
    1510
    16   // privat:
    17   float ****HVArray;
     11 private:
     12 
     13  double ****HVArray;
    1814  int ****DACArray;
    19 
    2015 
    2116  int NDACValues;
     
    2419 public:
    2520
    26 
    2721  HVCalib(HVConfig *hvConfig);
    2822  ~HVCalib();
    2923
    3024  int iDACMin;
    31   float fHVCalibSlope;
     25  double fHVCalibSlope;
    3226
    33   int HVToDAC(float hv, int board, int chain, int channel);
    34   float DACToHV(int dac, int board, int chain, int channel);
    35 
    36 
     27  int HVToDAC(double hv, int board, int chain, int channel);
     28  double DACToHV(int dac, int board, int chain, int channel);
    3729};
    3830
  • hvcontrol/src/HVConfig.cc

    r80 r90  
    1111\********************************************************************/
    1212
    13 
    14 #include "ReadCard.h"
    1513#include "HVConfig.h"
    1614
     
    1816HVConfig::HVConfig(FILE* fptr, char *configfile) {
    1917
    20   fLogPath   = new char[FILENAME_MAX_SIZE];
     18  fLogFile   = new char[BUFFER_LENGTH];
    2119  fUSBDevice = new char*[MAX_NUM_HVBOARDS];
    22   fCCClient  = new char[FILENAME_MAX_SIZE];
    2320
    24   fPixMapTable = new char[FILENAME_MAX_SIZE];
     21  fPixMapTable = new char[BUFFER_LENGTH];
    2522   
    2623  for (int i=0; i<MAX_NUM_HVBOARDS; i++) {
    27     fUSBDevice[i]      = new char[FILENAME_MAX_SIZE];
     24    fUSBDevice[i]      = new char[BUFFER_LENGTH];
    2825    USBDeviceNumber[i] = 0;
    2926
    30     for (int j=0; j<MAX_NUM_CHAINS; j++)
    31       for (int k=0; k<2; k++)
    32         Coef[i][j][k] = 0.;
     27    for (int j=0; j<NUM_CHAINS; j++) {
     28      for (int k=0; k<2; k++) Coef[i][j][k] = 0.;
     29    }
    3330  }
    3431
     
    3835  fStatusRefreshRate = 1.;
    3936  fTimeOut           = 1.;
    40   IsDAC              = true;
    4137  DACMin             = 11008;
    4238  DACMax             = 12496;
    43   HVMin              = 67.0;
    44   HVMax              = 76.0;
    4539  fHVCalibOffset      = -.8;
    4640  fHVCalibSlope       = 0.0064;
    47   fHVMaxDiff          = 1.0
     41  fHVMaxDiff          = 1
    4842
    4943  if (configfile != NULL) {
     
    5852HVConfig::~HVConfig() {
    5953
    60   delete [] fLogPath;
    61   delete [] fPixMapTable;
    62 
    63   for (int i=0; i<MAX_NUM_HVBOARDS; i++)
    64     delete [] fUSBDevice[i];
     54  delete [] fLogFile;   delete [] fPixMapTable;
     55  for (int i=0; i<MAX_NUM_HVBOARDS; i++) delete [] fUSBDevice[i];
    6556  delete [] fUSBDevice;
    66 
    6757}
    6858
     
    7868    return 0;
    7969  }
    80   else {
    81     fprintf(fptr,"Opening configuration file: %s\n", configfile);
    82   }
     70  else fprintf(fptr,"Opening configuration file: %s\n", configfile);
    8371 
    84   ReadCard("LogPath",    fLogPath,    's',f);
     72  ReadCard("LogFile",    fLogFile,    's',f);
     73  ReadCard("PixMapTable",fPixMapTable,'s',f);
     74  ReadCard("TestMode",   &str,        's',f);
     75  if (!strcmp(str,"TRUE")) TestMode = true;
    8576
    86   ReadCard("PixMapTable",fPixMapTable,'s',f);
    87 
    88   ReadCard("TestMode",   &str,        's',f);
    89   if (!strcmp(str,"TRUE"))
    90     TestMode = true;
    91 
    92 
    93   for (int i=0;i<MAX_NUM_HVBOARDS;i++) {
     77  for (int i=0; i<MAX_NUM_HVBOARDS; i++) {
    9478    sprintf(str,"Board%d",i);
    9579
    96     if (ReadCard(str, dev, 's', f)==0) {
     80    if (ReadCard(str, dev, 's', f)) {
    9781      USBDeviceNumber[j] = i;
    9882      sprintf(fUSBDevice[j++],"%s",dev);
     
    10488  ReadCard("StatusRefreshRate", &fStatusRefreshRate, 'f', f);
    10589  ReadCard("CCPort",            &fCCPort,            'I', f);
    106   ReadCard("CCClient",           fCCClient,          's', f);
    107   ReadCard("IsDAC",             &str,                's', f);
    10890  ReadCard("DACMin",            &DACMin,             'I', f);
    10991  ReadCard("DACMax",            &DACMax,             'I', f);
    110   ReadCard("HVMin",             &HVMin,              'f', f);
    111   ReadCard("HVMax",             &HVMax,              'f', f);
    11292  ReadCard("HVCalibOffset",     &fHVCalibOffset,     'f', f);
    11393  ReadCard("HVCalibSlope",      &fHVCalibSlope,      'f', f);
    114   ReadCard("HVMaxDiff",         &fHVMaxDiff,         'f', f);
     94  ReadCard("HVMaxDiff",         &fHVMaxDiff,         'U', f);
    11595
    116   if (strcmp(str,"TRUE"))
    117     IsDAC = false;
    118  
    11996  fclose(f);
    12097  return 1;
     
    124101int HVConfig::PrintHVConfig(FILE *fptr) {
    125102 
    126   fprintf(fptr,"\n");                                   
    127   fprintf(fptr,"********************************************* CONFIG ********************************************\n\n");
    128  
    129   fprintf(fptr," HV control configuration (%s):\n\n", FileName);
    130   fprintf(fptr," Log path:          %s\n\n", fLogPath);
    131   fprintf(fptr," Pixel map table:   %s\n\n", fPixMapTable);
    132   fprintf(fptr," Test mode:         %s\n\n", TestMode ? "yes" : "no");
    133   fprintf(fptr," %.2d USB devices:\n\n", NumHVBoards);
     103  fprintf(fptr," \n HV control configuration (%s):\n\n", FileName);
     104  fprintf(fptr," Log file:          %s\n", fLogFile);
     105  fprintf(fptr," Pixel map table:   %s\n", fPixMapTable);
     106  fprintf(fptr," Test mode:         %s\n", TestMode ? "yes" : "no");
     107  fprintf(fptr," %d USB devices:\n", NumHVBoards);
    134108 
    135109  for (int i=0;i<NumHVBoards;i++)
     
    138112  fprintf(fptr,"\n");
    139113  fprintf(fptr," TimeOut:           %.2f s\n",   fTimeOut);
    140   fprintf(fptr," StatusRefreshRate: %.2f Hz\n\n",fStatusRefreshRate);
     114  fprintf(fptr," StatusRefreshRate: %.2f Hz\n",fStatusRefreshRate);
    141115  fprintf(fptr," CCPort:            %d\n",       fCCPort);
    142   fprintf(fptr," CCClient:          %s\n\n",     fCCClient);
    143   fprintf(fptr," Set DAC values:    %s\n\n",     IsDAC ? "yes" : "no");
    144   fprintf(fptr," DACMin value:      %d\n\n",     DACMin);
    145   fprintf(fptr," DACMax value:      %d\n\n",     DACMax);
    146   fprintf(fptr," HVMin value:       %f\n\n",     HVMin);
    147   fprintf(fptr," HVMax value:       %f\n\n",     HVMax);
    148   fprintf(fptr," HVCalibOffset :    %f\n\n",     fHVCalibOffset);
    149   fprintf(fptr," HVCalibSlope :     %f\n\n",     fHVCalibSlope);
    150   fprintf(fptr," HVMaxDiff :        %f\n\n",     fHVMaxDiff);
     116  fprintf(fptr," DACMin value:      %d\n",     DACMin);
     117  fprintf(fptr," DACMax value:      %d\n",     DACMax);
     118  fprintf(fptr," HVCalibOffset :    %f\n",     fHVCalibOffset);
     119  fprintf(fptr," HVCalibSlope :     %f\n",     fHVCalibSlope);
     120  fprintf(fptr," HVMaxDiff :        %u\n",     fHVMaxDiff);
    151121 
    152   fprintf(fptr,"*************************************************************************************************\n\n");
    153 
    154122  return 1;
    155123}
    156124
     125// ReadCard function (original version by F. Goebel)
     126// Data is read into an array if MaxNum is larger than 1
     127bool ReadCard(const char *card_flag, void *store, char Type, FILE *File, unsigned int MaxNum) {
     128 
     129  char *card_name, *card_val, Buffer[MAX_COM_SIZE];
     130  unsigned int Count=0;
     131 
     132  rewind(File);
    157133
    158 int HVConfig::WriteHVConfig(FILE* fptr, char *configfile) {
     134  while (fgets(Buffer, sizeof(Buffer), File) != NULL) {    // Read line by line
     135    card_name = strtok(Buffer," \t\n");
     136   
     137     // Ignore empty lines, comments, and skip if card name does not match
     138    if (card_name==NULL || card_name[0]=='#' || strcmp(card_name, card_flag)!=0) continue;
    159139
    160   FILE *f;
    161 
    162   time_t time_now_secs;
    163   struct tm *time_now;
    164 
    165   time(&time_now_secs);
    166   time_now = localtime(&time_now_secs);
    167 
    168   if ((f = fopen(configfile,"w")) == NULL) {
    169     fprintf(fptr,"Could not open file: %s\n", configfile);
    170     return 0;
     140    // Read numbers of given type (if MaxNum>1 read array)
     141    while ((card_val=strtok(NULL," \t\n")) != NULL && Count++<MaxNum) {
     142      switch (Type) {
     143        case 'I': *(((int *&) store)++) = (int) strtol(card_val, NULL, 10);
     144                  break;
     145        case 'i': *(((short *&) store)++) = (short) strtol(card_val, NULL, 10);
     146                  break;
     147        case 'U': *(((unsigned int *&) store)++) = (unsigned int) strtoul(card_val, NULL, 10);
     148                  break;
     149        case 'u': *(((unsigned short *&) store)++) = (unsigned short) strtoul(card_val, NULL, 10);
     150                  break;
     151        case 'f': *(((float *&) store)++) = atof(card_val);
     152                  break;
     153        case 'd': *(((double *&) store)++) = atof(card_val);
     154                  break;
     155        case 's': sprintf((char *) store, "%s", card_val);
     156                  break;
     157        case 'c': *((char *) store) = card_val[0];
     158                  break;
     159        default:  fprintf(stderr,"Warning: Unknown type '%c' for reading of configuration file\n", Type);
     160                  return false;
     161      }
     162    }
     163    return true;  // Finished reading data for card name 
    171164  }
    172  
    173   fprintf(f,"# Main configuration file for the HV control program %s, %04d %02d %02d, %02d:%02d:%02d\n",
    174           HV_CONTROL_VERSION,
    175           1900 + time_now->tm_year,
    176           1 + time_now->tm_mon,
    177           time_now->tm_mday,
    178           time_now->tm_hour,
    179           time_now->tm_min,
    180           time_now->tm_sec);
    181 
    182   fprintf(f,"# Note: this file will be updated at program exit\n\n");
    183 
    184   fprintf(f,"LogPath            %s\n\n",   fLogPath);
    185   fprintf(f,"PixMapTable        %s\n\n",   fPixMapTable);
    186 
    187   fprintf(f,"TestMode           %s       #Test Mode: if no HV boards are connected, the test mode can be used.",((TestMode) ? "TRUE" : "FALSE"));
    188 
    189   fprintf(f,"TimeOut            %.2f s   # Timeout to return from read (%.2f,...%.2f) s\n\n",fTimeOut,MIN_TIMEOUT,MAX_TIMEOUT);
    190 
    191   fprintf(f,"StatusRefreshRate  %.2f Hz   # Status update rate (%.2f,...%.2f) Hz\n\n",fStatusRefreshRate,MIN_RATE,MAX_RATE);
    192 
    193   fprintf(f,"CCPort             %d   # Port used to look for commands from the Central Control\n",fCCPort);
    194   fprintf(f,"CCClient           %s   # Central Control client name\n\n",fCCClient);
    195   fprintf(f,"IsDAC              %s   # Define here if user input is interpreted as DAC value or voltage\n\n",((IsDAC) ? "TRUE" : "FALSE"));
    196   fprintf(f,"DACMin             %d   # Starting point for calibration of DAC to voltage values\n",DACMin);
    197   fprintf(f,"DACMax             %d   # End point for calibration of DAC to voltage values\n",DACMax);
    198   fprintf(f,"HVMin              %f   # Starting point for calibration of voltage to DAC values\n",HVMin);
    199   fprintf(f,"HVMax              %f   # End point for calibration of voltage to DAC values\n",HVMax);
    200   fprintf(f,"HVCalibOffset      %f   # Calibration of DAC to voltage values\n",fHVCalibOffset);
    201   fprintf(f,"HVCalibSlope       %f   # Calibration of DAC to voltage values\n\n",fHVCalibSlope);
    202   fprintf(f,"HVMaxDiff          %f   # Speed for HV changes limited to 1V/ms\n",fHVMaxDiff);
    203 
    204   fprintf(f,"# List of HV boards (at most %d HV boards will be recognized):\n",MAX_NUM_HVBOARDS);
    205 
    206   for (int i=0;i<NumHVBoards;i++)
    207     fprintf(f,"Board%d             %s\n",USBDeviceNumber[i],fUSBDevice[i]);
    208  
    209   fprintf(fptr,"Configuration file successfully updated\n");
    210  
    211   fclose(f);
    212   return 1;
    213 
     165  return false;
    214166}
    215167
    216 
  • hvcontrol/src/HVConfig.h

    r80 r90  
    44
    55#include <time.h>
     6#include <string.h>
     7#include <stdlib.h>
     8#include <stdio.h>
    69
    7 #include <string.h>
     10#define MAX_COM_SIZE 1000
     11#define MAX_NUM_HVBOARDS 20
     12#define NUM_CHAINS 4
     13#define NUM_CHANNELS 32
     14#define BUFFER_LENGTH 256
    815
    9 #include "Types.h"
     16#define MIN_TIMEOUT 0.01
     17#define MAX_TIMEOUT 5.0
     18
     19#define MIN_RATE 0.01
     20#define MAX_RATE 50.0
     21
    1022
    1123class HVConfig {
     
    1830  int ReadHVConfig(FILE* fptr, char *configfile);
    1931  int PrintHVConfig(FILE* fptr);
    20   int WriteHVConfig(FILE* fptr, char *configfile);
    2132
    2233  int NumHVBoards;
     
    2435
    2536  int fCCPort;
    26   char *fCCClient;
    2737
    2838  bool TestMode;
    2939
    30   bool IsDAC;
    31   float Coef[MAX_NUM_HVBOARDS][MAX_NUM_CHAINS][2];
     40  float Coef[MAX_NUM_HVBOARDS][NUM_CHAINS][2];
    3241 
    3342  char*  FileName;
    34   char*  fLogPath;
     43  char*  fLogFile;
    3544  char** fUSBDevice;
    3645
     
    4251  int DACMin;
    4352  int DACMax;
    44   float HVMin;
    45   float HVMax;
    4653
    4754  float  fHVCalibOffset;
    4855  float  fHVCalibSlope;
    49   float  fHVMaxDiff;
     56 
     57  unsigned int  fHVMaxDiff;
    5058
    5159};
    5260
     61bool ReadCard(const char *, void *, char, FILE *, unsigned int=1);
     62
    5363#endif
  • hvcontrol/src/ProcessIO.cc

    r80 r90  
    22/********************************************************************\
    33
    4   Name:         ProcessIO.cc
    5 
    6   Created by:   Sebastian Commichau, November 2008
    7                 commichau@phys.ethz.ch
    8 
    9   Contents:     Main class processing user input
     4  ProcessIO.cc
     5
     6  Main class processing user input
     7 
     8  Sebastian Commichau, Sabrina Stark-Schneebeli, Oliver Grimm
    109
    1110\********************************************************************/
    1211
    13 
    1412#include "ProcessIO.h"
    1513
     14static char* state_str[]    = {"active", "stopped", "n.a."};
    1615
    1716ProcessIO::ProcessIO(char *ConfigFile) {
    1817
    19   // Get program start time - only needed for uptime command
     18  // Get program start time
    2019  time (&StartTime);
    2120
    22   status  = new Status;
    23   config  = new HVConfig(stdout,ConfigFile);
     21  // Create instances
     22  config = new HVConfig(stdout,ConfigFile);
    2423  calib  = new HVCalib(config);
    25   log     = new Log(config->fLogPath);
    26   hv      = new HV(config->fUSBDevice,config->USBDeviceNumber,stdout,config->TestMode);
    27  
    28   pm = new PixelMap(config->fPixMapTable);
    29 
    30   // Initialize status structure (HVStatus.cc/h)
    31   InitStatus(status,config);   
    32 
    33   // Print HV control configuration to the log file
    34   config->PrintHVConfig(log->logptr);
    35 
    36   // The following loop was added to allow for an arbitrary numeration of the HV boards
    37   for (int i=0;i<hv->GetNumberOfBoards();i++) {
    38    
    39     sprintf(status->fUSBDevice[i],"%s",(hv->GetHVBoard(i))->GetSerial());
    40     status->USBDeviceNumber[i] = (hv->GetHVBoard(i))->GetBoardNumber();
    41 
    42     if ((hv->GetHVBoard(i))->GetBoardNumber() > status->USBMaxDeviceNumber)
    43       status->USBMaxDeviceNumber = (hv->GetHVBoard(i))->GetBoardNumber();
    44 
    45     if ((hv->GetHVBoard(i))->GetBoardNumber() < status->USBMinDeviceNumber)
    46       status->USBMinDeviceNumber = (hv->GetHVBoard(i))->GetBoardNumber();
    47 
    48     (hv->GetHVBoard(i))->SetTimeOut(config->fTimeOut);
    49   }
    50 
    51   // Initialize HV boards (see below)
    52   InitializeHV();
    53 
    54   status->FirstBoard  = 0;
    55   status->NumHVBoards = hv->GetNumberOfBoards();
    56   status->LastBoard   = hv->GetNumberOfBoards()-1;
    57 
    58   // Print status information to the log file
    59   PrintStatus(status,config,log->logptr);
    60 
    61   // Send reset command to all boards
    62   ResetAllBoards();
    63 
    64   // Print some information
    65   sprintf(str,"status monitor: %s\n", GetStateStr(status));
    66   if (hv->GetNumberOfBoards()>0) DoPrompt(str);
    67  
    68   sprintf(str,"type (h)elp to get a list of available commands\n");
    69   DoPrompt(str);
    70 
    71   // Print empty prompt
    72   DoPrompt(NULL);
    73  
    74   // Initialize mutex variable for thread synchronization
    75   pthread_mutex_init (&control_mutex, NULL);
    76   pthread_cond_init  (&control_cond,  NULL);
    77  
    78   sprintf(str,"**************** End of constructor ProcessIO ************\n");
    79   DoPrompt(str);
    80  
    81 }
    82 
    83 
    84 ProcessIO::~ProcessIO() {
    85  
    86   pthread_mutex_destroy (&control_mutex);
    87   pthread_cond_destroy  (&control_cond);
    88  
    89   config->fStatusRefreshRate = status->fStatusRefreshRate;
    90   config->fTimeOut           = status->fTimeOut;
    91   config->WriteHVConfig(stdout,config->FileName);
    92 
    93   delete hv;
    94   delete status;
    95   delete config;
    96   delete log;
    97   delete pm;
    98  
    99 }
    100 
    101 
    102 // Print list of all commands
    103 void ProcessIO::PrintHelp() {
    104 
    105   puts("");
    106   puts("********************************************** HELP *********************************************\n");
    107   puts(" board <i>|<i> <j>|<all>           Address board i, boards i-j or all boards");
    108   puts(" chain <i>|<i> <j>|<all>           Address chain i, chains i-j or all chains");
    109   puts(" clear                             Clear screen");
    110   puts(" config                            Print configuration");
    111   puts(" help                              Print help");
    112   puts(" hv <ch>|<all> [b][x]<v>           Set chan. <ch>|<all> chan. of active chain(s)/board(s) to <v>");
    113   //  puts(" hvdiff <ch>|<all> [b][x]<diff>    Set chan. <ch>|<all> chan. of active chain(s)/board(s) to <diff>");
    114   puts(" hvdiff <PXL id> <diff>            Set HV difference of pixel PXL id to <diff>");
    115   puts(" list                              List all HV boards");
    116   puts(" load <file>                       Load HV settings from <file>");
    117   puts(" log <on>|<off>                    Enable|disable logging");
    118   puts(" quit|exit                         Exit program");
    119   puts(" rate <rate>                       Set status refresh rate to <rate> [Hz]");
    120   puts(" reset                             Reset active HV board");
    121   puts(" save [file]                       Save current HV settings to [file]");
    122   puts(" start                             Start HV status monitor");
    123   puts(" status                            Show status information");
    124   puts(" stop                              Stop HV status monitor - not recommended!");
    125   puts(" time                              Print current date and time");
    126   puts(" timeout <time>                    Set timeout to return from read to <time> [s]");
    127   puts(" uptime                            Get program uptime [h:m:s]");
    128   puts(" verbose <on>|<off>                Enable|disable verbosity");
    129   puts(" vref [b][x]<v>                    Set reference voltage of active chain(s)/board(s) to <v>\n");
    130   puts("*************************************************************************************************\n");
    131 
    132 }
    133 
    134 
    135 // Process user input
    136 int ProcessIO::CommandControl() {
    137 
    138 
    139   // Adress HV board
    140   if (Match(status->Param[0], "board")) {
    141    
    142     if (!NBoards())
    143       return 0;
    144     else {
    145  
    146       // Select all boards
    147       if (status->Param[1][0] == 'a' && !status->Param[2][0]) {
    148        
    149         status->FirstBoard = 0;
    150         status->LastBoard = hv->GetNumberOfBoards()-1;
    151        
    152       }
    153       // Wrong type of argument
    154       else if (!IsNoDigit(status->Param[1]) || !IsNoDigit(status->Param[2]) || status->Param[3][0] || !status->Param[1][0]) {
    155         sprintf(str,"ERROR - usage: <board> <i>|<i> <j>|<all>\n");
    156         DoPrompt(str); 
    157         return 0;
    158       }
    159       // Check if board(s) exist(s)
    160       else if (status->Param[1][0] || status->Param[2][0]) {
    161 
    162         if (!IsBoard(atoi(status->Param[1]))) {
    163           sprintf(str,"ERROR -board #%d does not exist\n", atoi(status->Param[1]));
    164           DoPrompt(str);
    165           return 0;
    166         }
    167        
    168         if (status->Param[2][0])
    169           if (!IsBoard(atoi(status->Param[2]))) {
    170             sprintf(str,"ERROR -board #%d does not exist\n", atoi(status->Param[2]));
    171             DoPrompt(str);
    172             return 0;
    173           }
    174 
    175         if (status->Param[1][0] && status->Param[2][0]) {
    176          
    177           status->FirstBoard = GetBoardIdx(atoi(status->Param[1]));
    178           status->LastBoard  = GetBoardIdx(atoi(status->Param[2]));
    179 
    180         }
    181         else if (status->Param[1][0]) {
    182 
    183           status->FirstBoard = GetBoardIdx(atoi(status->Param[1]));
    184           status->LastBoard = status->FirstBoard;
    185          
    186         }
    187       }
    188    
    189       //DoPrompt(NULL);
    190     }
    191    
    192     DoPrompt(NULL);
    193     return 0;
    194   }
    195 
    196 
    197   // Adress chains
    198   else if (Match(status->Param[0], "chain")) {
    199    
    200     if (!NBoards())
    201       return 0;
    202     else {
    203      
    204       if (status->Param[1][0] == 'a') {
    205        
    206         status->FirstChain = 0;
    207         status->LastChain  = 3;
    208        
    209       }
    210       else if (!IsNoDigit(status->Param[1]) || !status->Param[1][0]) {
    211         sprintf(str,"ERROR -usage: <chain> <i>|<i> <j>|<all>\n");
    212         DoPrompt(str); 
    213         return 0;
    214       }
    215       else if (status->Param[1][0] >= 0 && atoi(status->Param[1]) >= 0 && atoi(status->Param[1]) < 4 && !status->Param[2][0]) {
    216        
    217         status->FirstChain = atoi(status->Param[1]);
    218         status->LastChain = status->FirstChain;
    219        
    220       }
    221       else if ((status->Param[1][0] >= 0 && atoi(status->Param[1]) >= 0 && atoi(status->Param[1]) < 4) &&
    222                (status->Param[2][0] > 0 && atoi(status->Param[2]) > 0 && atoi(status->Param[2]) < 4)) {
    223        
    224         status->FirstChain = atoi(status->Param[1]);
    225         status->LastChain = atoi(status->Param[2]);
    226        
     24  pm     = new PixelMap(config->fPixMapTable);
     25
     26  // Initialize status variables
     27  state     = active;
     28  Exit      = false;
     29  Verbose   = false;
     30  CmdFromSocket = false;
     31  Socket    = -1;
     32 
     33  NumHVBoards = 0;
     34  FirstBoard  = 0;
     35  LastBoard   = -1;
     36  FirstChain  = 0;
     37  LastChain   = 3;
     38 
     39  if (config->fStatusRefreshRate >= MIN_RATE && config->fStatusRefreshRate <= MAX_RATE)
     40    fStatusRefreshRate = config->fStatusRefreshRate;
     41  else fStatusRefreshRate = 1.;
     42   
     43  // Open HV devices
     44  if(config->TestMode){
     45    fprintf(stdout,"Test mode: One HVBoard initialized as dummy.\n");
     46    fHVBoard[NumHVBoards] = new HVBoard(0, 0, config->TestMode, config->fTimeOut, Verbose);
     47    NumHVBoards++;
     48  }
     49  else {
     50    for (int i=0; i<config->NumHVBoards; i++) {
     51      fHVBoard[NumHVBoards] = new HVBoard(config->USBDeviceNumber[i], config->fUSBDevice[i], config->TestMode, config->fTimeOut, Verbose);
     52      if(fHVBoard[NumHVBoards]->fDescriptor >= 0) {
     53         printf("Synchronized and reset HV board %d (%s)\n",i,config->fUSBDevice[i]);
     54         NumHVBoards++;
    22755      }
    22856      else {
    229        
    230         if (atoi(status->Param[1]) < 0 || atoi(status->Param[1]) > 3) {
    231           sprintf(str,"ERROR -chain #%d does not exist\n", atoi(status->Param[1]));
    232           DoPrompt(str);
    233         }
    234        
    235        
    236         if ((atoi(status->Param[2]) < 0 || atoi(status->Param[2]) > 3) && (atoi(status->Param[1]) != atoi(status->Param[2]))) {
    237           sprintf(str,"ERROR -chain #%d does not exist\n", atoi(status->Param[2]));
    238           DoPrompt(str);
    239         }
    240        
    241         return 0;
    242        
     57        printf("Failed to synchronize to HV board %d (%s)\n",i,config->fUSBDevice[i]);
     58        delete fHVBoard[NumHVBoards];
    24359      }
    244 
    245       DoPrompt(NULL);
    246     }
    247    
    248     return 0;
     60    }
    24961  }
    250 
    251 
    252   // Clear screen
    253   else if (Match(status->Param[0], "clear") || Match(status->Param[0], "cls")) {
    254 
    255   system("clear");
    256   DoPrompt(NULL);
    257 
    258   return 0;
    259  
    260   }
     62  LastBoard = NumHVBoards-1;
     63
     64  // Open log file
     65  if ((Logfile = fopen(config->fLogFile, "a")) == NULL) printf("Warning: Could not open log file '%s'\n", config->fLogFile);
     66  PrintMessage(MsgToLog,"********** Logging started **********\n");
     67
     68  // Print configuration to log file
     69  if(Logfile) config->PrintHVConfig(Logfile);
     70}
     71
     72
     73ProcessIO::~ProcessIO() {
     74 
     75  for (int i=0; i<NumHVBoards; i++) delete fHVBoard[i];
     76
     77  delete config;    delete pm;
     78 
     79  if(Logfile != NULL) {
     80    if(!fclose(Logfile)) printf("Closing logfile\n");
     81    else perror("Error closing logfile");
     82  }
     83}
     84
     85
     86// Process user input
     87void ProcessIO::CommandControl(char *Command) {
     88
     89  if (strlen(Command)==0) return;  // Ignore empty commands
     90
     91  if(Command[0]=='.') {   // Shell command
     92    system(&(Command[1]));
     93    return;
     94  }
     95
     96  for(int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = "";  // All pointers point initially to empty string
     97    NParam = ParseInput(Command, Param);
     98
     99  // Adress HV board
     100  if (Match(Param[0], "board")) {
     101   
     102    if (!NumHVBoards) return;
     103
     104    // Print list of boards
     105    if (NParam == 1) {
     106      for (int i=0; i<NumHVBoards; i++) {
     107        PrintMessage("Board %d: %s\n", fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName);
     108      }
     109      return;
     110    }
     111
     112    //Select board(s)
     113    if (Match(Param[1],"all")) {
     114      FirstBoard = 0;
     115      LastBoard = NumHVBoards-1;
     116    }
     117    else if (NParam==2 && atoi(Param[1])>=0 && atoi(Param[1])<NumHVBoards) {
     118      FirstBoard = atoi(Param[1]);
     119      LastBoard = FirstBoard;
     120    }
     121    else if (NParam==3 && atoi(Param[1])>=0 && atoi(Param[1])<NumHVBoards &&
     122           atoi(Param[2])>0 && atoi(Param[2])<NumHVBoards) {
     123      FirstBoard = atoi(Param[1]);
     124      LastBoard = atoi(Param[2]);
     125    }
     126    else PrintMessage("Cannot address board(s), out of range.\n");
     127
     128    return;
     129  }
     130
     131
     132  // Adress chains
     133  else if (Match(Param[0], "chain")) {
     134   
     135    if (!NumHVBoards) return;
     136   
     137    if (Match(Param[1],"all")) {
     138      FirstChain = 0;
     139      LastChain = 3;
     140    }
     141    else if (NParam==2 && atoi(Param[1])>=0 && atoi(Param[1])<4) {
     142      FirstChain = atoi(Param[1]);
     143      LastChain = FirstChain;
     144    }
     145    else if (NParam==3 && atoi(Param[1])>=0 && atoi(Param[1])<4 &&
     146           atoi(Param[2])>0 && atoi(Param[2])<4) {
     147      FirstChain = atoi(Param[1]);
     148      LastChain = atoi(Param[2]);
     149    }
     150    else PrintMessage("Cannot address chain(s), out of range.\n");
     151       
     152    return;
     153  }
    261154
    262155
    263156  // Print HV utility configuration
    264   else if (Match(status->Param[0], "config")) {
     157  else if (Match(Param[0], "config")) {
    265158
    266159    config->PrintHVConfig(stdout);
    267160   
    268     return 0;
     161    return;
    269162  }
    270163
    271164
    272165  // Print help
    273   if (Match(status->Param[0], "help")) {
    274 
    275     PrintHelp();
    276     DoPrompt(NULL);
    277    
    278     return 0;
     166  if (Match(Param[0], "help")) {
     167    puts(" board <i>|<i> <j>|<all>           Address board i, boards i-j or all boards or list boards");
     168    puts(" chain <i>|<i> <j>|<all>           Address chain i, chains i-j or all chains");
     169    puts(" hv <PXL id>|<ch>|<all> <v>        Set HV of pixel ID, ch. or all ch. of active chain(s)/board(s)");
     170    puts(" hvdiff <PXL id>|<ch>|<all> <diff> Change HV by <diff>");
     171    puts(" status [dac]                      Show status information (DAC values if requested)");
     172    puts(" config                            Print configuration");
     173    puts(" load <file>                       Load HV settings from <file>");
     174    puts(" save <file>                       Save current HV settings to [file]");
     175    puts(" exit                              Exit program");
     176    puts(" rate <rate>                       Set status refresh rate to <rate> [Hz]");
     177    puts(" timeout <time>                    Set timeout to return from read to <time> [s]");
     178    puts(" reset                             Reset active HV board");
     179    puts(" start                             Start HV status monitor");
     180    puts(" stop                              Stop HV status monitor - not recommended!");
     181    puts(" uptime                            Get program uptime [h:m:s]");
     182    puts(" verbose <on|off>|                 Enable|disable verbosity");
     183    puts(" help                              Print help");
     184    puts(" .<cmd>                            Execute shell command <cmd>");
     185
     186    return;
    279187  }
    280188
    281189
    282   // Write high voltage -----------------------------------------------------------------------------------------
    283   if (Match(status->Param[0], "hv")) {
    284 
    285     if (!NBoards())
    286       return 0;
    287 
    288     int errors = 0;
    289     unsigned int hvoltage = 0, hvAll = 0;
    290     float hvoltageV = 0.0;
    291     int channel = 0, hvdiff = 0;
    292     bool allchannels = FALSE;
    293 
    294     if (status->Param[1][0]>0 && status->Param[2][0]>0) {
    295 
    296       // Set channel
    297       if (IsNoDigit(status->Param[1]))
    298         channel = atoi(status->Param[1]);
    299       else if(status->Param[1][0] == 'a')
    300         allchannels = TRUE;
    301       else {
    302         DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n");
    303         return 0;
    304       }
    305          
    306       // Binary input
    307       if (tolower(status->Param[2][0])=='x' && strlen(status->Param[2])>2) {
    308         if (sPrintHex2Dec(Chop(status->Param[2]+1),&hvoltage)!=0) {
    309           DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n");
    310           return 0;
    311         }
    312       }
    313       // Hexadecimal input
    314       else if (tolower(status->Param[2][0])=='b' && strlen(status->Param[2])>2) {
    315         if (sPrintBin2Dec(Chop(status->Param[2]+1),&hvoltage)!=0) {
    316           DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n");
    317           return 0;
    318         }
    319       }
    320       // Decimal input
    321       else if (IsNoDigit(status->Param[2])&&config->IsDAC)
    322         hvoltage = atoi(status->Param[2]);
    323       else if (IsNoDigit(status->Param[2])&&(!(config->IsDAC)))
    324         hvoltageV = atof(status->Param[2]);
    325       // Wrong input format
    326       else {
    327         DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n");
    328         return 0;
    329       }
    330 
    331       // Check limits
    332       if (channel>31 || channel <0) {
    333         DoPrompt("ERROR - channel out of range (0...31)!\n");
    334         return 0;
    335       }
    336       else if ((hvoltage>0X3FFF || hvoltage <0)&&config->IsDAC) {
    337         DoPrompt("ERROR - high voltage out of range (Vmin: 0, Vmax: 16383)!\n");
    338         return 0;
    339       }
    340       else if ((hvoltage>78.0 || hvoltage <0)&&(!(config->IsDAC))) {
    341         DoPrompt("ERROR - high voltage out of range (Vmin: 0, Vmax: 78.)!\n");
    342         return 0;
    343       }
    344 
    345       StopMonitor();
    346 
    347      
    348       for (int i=status->FirstBoard;i<=status->LastBoard;i++) {
    349 
    350         for (int j=status->FirstChain;j<=status->LastChain;j++) {
    351           if (!allchannels) {
    352  // Convert from HV to DAC values
    353             if (!(config->IsDAC)){
    354               status->HVV[i][j][channel]=hvoltageV;
    355               hvoltage = calib->HVToDAC(hvoltageV,i,j,channel);
    356             }
    357             hvdiff = hvoltage - status->HV[i][j][channel];
    358             for (int k=0;k<=abs((int)(hvdiff/config->fHVMaxDiff));k++){
    359               if (k<abs((int)(hvdiff/config->fHVMaxDiff))){
    360                 hvoltage=(unsigned int)(status->HV[i][j][channel] + config->fHVMaxDiff*hvdiff/abs(hvdiff));
    361               }
    362               if (k==(abs((int)(hvdiff/config->fHVMaxDiff)))){
    363                 hvoltage=(unsigned int)(status->HV[i][j][channel] + (hvdiff%(int)config->fHVMaxDiff));
    364               }
    365              
    366               if ((hv->GetHVBoard(i))->SetHV(stdout,j,channel,hvoltage,rbuf,status->Verbose)==1){
    367                 status->HV[i][j][channel]=hvoltage;
    368                 UpdateStatus(i,rbuf);
    369                
    370                 sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",hv->GetHVBoard(i)->GetBoardNumber(),j,channel,hvoltage,hvoltage,calib->DACToHV(hvoltage,hv->GetHVBoard(i)->GetBoardNumber(),j,channel));
    371                 //              DoPrompt(str);
    372                 if (status->Verbose) {
    373                   sPrintStatus(status,str,i);
    374                   DoPrompt(str);
    375                 }
    376                 sPrintStatus(status,str,i); // Print status only to socket
    377               }
    378               else {
    379                 sprintf(str,"ERROR - board %d error: could not set hv - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber());
    380                 DoPrompt(str);
    381                 errors++;
    382               }
    383             }
     190  // Set new high voltage --------------------------------------------------------------------------------------
     191  if (Match(Param[0], "hv") || Match(Param[0], "hvdiff")) {
     192
     193    if (!NumHVBoards) return;
     194
     195    int hvoltage, DACValue, Errors=0, Board, Chain=0, Channel=0;
     196    double hvoltageV;
     197    bool allchannels = false, SetDac = false;
     198   
     199    // Need two parameters or three if last is 'dac'
     200    if (NParam<3 || NParam>4) {
     201      PrintMessage("ERROR - usage: hv <channel>|<all> <voltage> [dac]\n");
     202      return;
     203    }
     204
     205    if (NParam==4 && Match(Param[3], "dac")) SetDac = true;
     206   
     207    // Evaluate pixel or channel parameter   
     208    if((Board = pm->Pixel_to_HVboard(Param[1])) != 999999999) {
     209      Chain = pm->Pixel_to_HVchain(Param[1]);
     210      Channel = pm->Pixel_to_HVchannel(Param[1]);
     211    }
     212    else if (Match(Param[1], "all")) allchannels = true;
     213    else if (ConvertToInt(Param[1], &Channel)) {
     214      Board = -1;
     215      Chain = -1;
     216    }
     217    else {
     218      PrintMessage("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n");
     219      return;
     220    }
     221    // Check channel limits (voltage limit is only checked in SetHV())
     222    if (Channel<0 || Channel>31) {
     223      PrintMessage("ERROR - channel out of range (0...31)!\n");
     224      return;
     225    }
     226
     227    if (SetDac && !ConvertToInt(Param[2], &hvoltage)) {
     228      PrintMessage("ERROR - wrong number format for DAC voltage setting\n");
     229      return;
     230    }
     231    if (!SetDac && !ConvertToDouble(Param[2], &hvoltageV)) {
     232      PrintMessage("ERROR - wrong number format for voltage setting\n");
     233      return;
     234    }
     235
     236    for (int i=FirstBoard; i<=LastBoard; i++) {
     237      if (!allchannels && Board != 999999999 && i != Board && Board!=-1) continue;
     238
     239      for (int j=FirstChain; j<=LastChain; j++) {
     240        if (!allchannels && Chain != 999999999 && j != Chain && Chain!=-1) continue;
     241
     242        for (int k=0; k<NUM_CHANNELS; k++) {
     243          if (!allchannels && k!= Channel) continue;
     244
     245          // Convert from HV to DAC values
     246          if (!SetDac){
     247            if(strlen(Param[0]) > 2) fHVBoard[i]->HVV[j][k] += hvoltageV; // hvdiff
     248            else fHVBoard[i]->HVV[j][k] = hvoltageV;
     249            DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k);
    384250          }
    385251          else {
    386             sprintf(str,"OK - updating board %d chain %d\n",hv->GetHVBoard(i)->GetBoardNumber(),j);
    387             DoPrompt(str);
     252            if(strlen(Param[0]) > 2) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // hvdiff
     253            else DACValue = hvoltage;
     254          }
    388255         
    389             for (int k=0;k<MAX_NUM_CHANNELS;k++) {
    390  // Convert from HV to DAC values
    391               if (!(config->IsDAC)){
    392                 status->HVV[i][j][k]=hvoltageV;
    393                 hvoltage = calib->HVToDAC(hvoltageV,i,j,k);
    394               }
    395               hvAll = hvoltage;
    396               hvdiff = hvAll - status->HV[i][j][k];
    397               for (int l=0;l<=abs((int)(hvdiff/config->fHVMaxDiff));l++){
    398                 if (l<abs((int)(hvdiff/config->fHVMaxDiff))){
    399                   hvoltage=(unsigned int)(status->HV[i][j][k] + config->fHVMaxDiff*hvdiff/abs(hvdiff));
    400                 }
    401                 if (l==(abs((int)(hvdiff/config->fHVMaxDiff)))){
    402                   hvoltage=(unsigned int)(status->HV[i][j][k] + (hvdiff%(int)config->fHVMaxDiff));
    403                 }
    404                 if ((hv->GetHVBoard(i))->SetHV(stdout,j,k,hvoltage,rbuf,status->Verbose)==1) {
    405                   status->HV[i][j][k]=hvoltage;
    406                   UpdateStatus(i,rbuf);
    407                  
    408                   if (status->Verbose) {
    409                     sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",hv->GetHVBoard(i)->GetBoardNumber(),j,channel,hvoltage,hvoltage,calib->DACToHV(hvoltage,hv->GetHVBoard(i)->GetBoardNumber(),j,channel));
    410                     //sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",hv->GetHVBoard(i)->GetBoardNumber(),j,k,hvoltage,hvoltage);
    411                     //   DoPrompt(str);
    412                     sPrintStatus(status,str,i);
    413                     DoPrompt(str);
    414                   }
    415                   sPrintStatus(status,str,i); // Print status only to socket
    416                 }
    417                
    418                 else {
    419                   sprintf(str,"ERROR - board %d error: could not set HV - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber());
    420                   DoPrompt(str);
    421                   errors++;
    422                 }
    423               }
     256          // Set new voltage (if DAC value, update calilbrated value)
     257          if(!RampVoltage(DACValue, i, j, k)) Errors++;
     258          else if(SetDac) fHVBoard[i]->HVV[j][k] = calib->DACToHV(fHVBoard[i]->HV[j][k], i, j, k);
     259
     260        } // Channels   
     261      } // Chains
     262    } // Boards
     263
     264    if (Errors > 0) PrintMessage("Warning: Errors on %d channel(s) occurred\n", Errors);
     265    else PrintMessage("OK - no error(s)\n");
     266   
     267    return;
     268  }
     269
     270
     271  // Load HV settings from file
     272  else if (Match(Param[0], "load")) {
     273
     274    char Buffer[MAX_COM_SIZE];
     275    int NBoards = 0, Errors = 0, Chain;
     276    unsigned int DACValue;
     277    FILE *File;
     278   
     279    if (NParam != 2) {
     280      PrintMessage("Usage: load <file>\n");
     281      return;
     282    }
     283   
     284    if ((File=fopen(Param[1], "r")) == NULL) {
     285      PrintMessage("Error: Could not open file '%s' (%s)\n", Param[1], strerror(errno));
     286      return;
     287    }
     288       
     289    StopMonitor();
     290
     291    while (fgets(Buffer, sizeof(Buffer), File) != NULL) {
     292      for (int Board=0; Board<NumHVBoards; Board++) {
     293        if (Match(fHVBoard[Board]->BoardName, Buffer)) {
     294
     295          PrintMessage("Found HV settings for board %d (%s)\n",fHVBoard[Board]->GetBoardNumber(), fHVBoard[Board]->BoardName);
     296
     297          Chain = 0;
     298          while (fgets(Buffer, sizeof(Buffer), File) && Chain<NUM_CHAINS) {
     299            if (strlen(Buffer) == 1) continue;  // Ignore if only newline character
     300
     301            for (int Channel=0; Channel<NUM_CHANNELS; Channel++) {
     302              if (sscanf(Buffer, "%u", &DACValue) != 1) {
     303                PrintMessage("Error reading DAC values from file, terminating\n");
     304                return;
     305              }       
     306              if (!RampVoltage(DACValue, Board, Chain, Channel)) Errors++;
    424307            }
     308            Chain++;
    425309          }
     310          PrintMessage("Finished updating board.\n");
     311          NBoards++;
    426312        }
    427       }
    428 
    429      
    430 
    431       StartMonitor();
    432 
    433       if (errors) {
    434         sprintf(str,"ERROR - warning %d error(s) => check timeout and try again\n",errors);
    435         DoPrompt(str);
    436       }
    437       else {
    438         sprintf(str,"OK - no error(s)... success!\n");
    439         DoPrompt(str);
    440       }
    441 
    442     }
    443     else {
    444       sprintf(str,"ERROR - usage: hv <channel>|<all> <voltage>\n");
    445       DoPrompt(str);
    446     }
    447 
    448     return 0;
    449   }  // End: Write high voltage  ----------------------------------------------------------------------------------------
    450 
    451 
    452 
    453   // Write difference of high voltage ------------------------------------------------------------------------------------
    454   if (Match(status->Param[0], "hvdiff")) {
    455 
    456     if (!NBoards())
    457       return 0;
    458 
    459     int errors = 0;
    460     int hvdiff = 0;
    461     unsigned int hvoltage = 0;
    462     float hvoltageV = 0.0;
    463     float hvdiffV = 0.0;
    464     std::string pixelname(status->Param[1]);
    465     unsigned int board = 0;
    466     unsigned int chain = 0;
    467     unsigned int channel = 0;
    468 
    469 
    470     if (status->Param[1][0]>0 && status->Param[2][0]>0) {
    471 
    472 
    473       // Set board
    474       board = pm->Pixel_to_HVboard(pixelname);
    475       //      std::cout << "Board: " << board << std::endl;
    476       // Set chain
    477       chain = pm->Pixel_to_HVchain(status->Param[1]);
    478       //      std::cout << "Chain: " << chain << std::endl;
    479       // Set channel
    480       channel = pm->Pixel_to_HVchannel(status->Param[1]);
    481       //      std::cout << "Channel: " << channel << std::endl;
    482 
    483       // Binary input
    484       if (tolower(status->Param[2][0])=='x' && strlen(status->Param[2])>2) {
    485         if (sPrintHex2Dec(Chop(status->Param[2]+1),(unsigned int *)hvdiff)!=0) {
    486           DoPrompt("ERROR - wrong input format - usage: hvdiff <channel>|<all> <hv difference>\n");
    487           return 0;
    488         }
    489       }
    490       // Hexadecimal input
    491       else if (tolower(status->Param[2][0])=='b' && strlen(status->Param[2])>2) {
    492         if (sPrintBin2Dec(Chop(status->Param[2]+1),(unsigned int *)hvdiff)!=0) {
    493           DoPrompt("ERROR - wrong input format - usage: hvdiff <channel>|<all> <hv difference>\n");
    494           return 0;
    495         }
    496       }
    497       // Decimal input
    498       else if (IsNoDigit(status->Param[2])&&(config->IsDAC))
    499         hvdiff = atoi(status->Param[2]);
    500       else if (IsNoDigit(status->Param[2])&&(!(config->IsDAC)))
    501         hvdiffV = atof(status->Param[2]);
    502       // Wrong input format
    503       else {
    504         DoPrompt("ERROR - wrong input format - usage: hvdiff <channel>|<all> <hv difference>\n");
    505         return 0;
    506       }
    507       // Check limits
    508       if (channel>31 || channel <0) {
    509         sprintf(str,"ERROR - channel out of range (0...31)!\n");
    510         DoPrompt(str);
    511         return 0;
    512       }
    513       else if (hvdiff>config->DACMax || hvdiff <(-(config->DACMax))) {
    514         sprintf(str,"ERROR - difference of high voltage [hvdiff:%d] out of range (Vmin: 0.0, Vmax: %d)!\n", hvdiff,config->DACMax);
    515         DoPrompt(str);
    516         return 0;
    517       }
    518       else if (hvdiffV>(calib->DACToHV(config->DACMax,0,0,0))|| hvdiffV<-(calib->DACToHV(config->DACMax,0,0,0))) {
    519         sprintf(str,"ERROR - difference of high voltage [hvdiff:%f] out of range (Vmin: 0.0, Vmax: %f)!\n",hvdiffV,calib->DACToHV(config->DACMax,0,0,0));
    520         DoPrompt(str);
    521         return 0;
    522       }
    523      
    524 
    525 
    526       //Convert from HV to DAC values
    527       if (!(config->IsDAC)){
    528         hvoltageV = status->HVV[board][chain][channel]+hvdiffV;
    529         status->HVV[board][chain][channel] = hvoltageV;
    530         //      printf("hv+diff = %f .\n",hvoltageV);
    531         hvdiff = calib->HVToDAC(hvoltageV,board,chain,channel) - status->HV[board][chain][channel];
    532         //      printf("dac new = %d, dac old = %d.\n",calib->HVToDAC(hvoltageV,board,chain,channel),status->HV[board][chain][channel]);
    533         //      printf("dac diff = %d .\n",hvdiff);
    534       }
    535       StopMonitor();
    536 
    537    
    538      
    539       hvoltage = status->HV[board][chain][channel];
    540       //      printf("dac hv = %d .\n",hvoltage);
    541       for (int k=0;k<=abs((int)(hvdiff/config->fHVMaxDiff));k++){
    542         if (k<abs((int)(hvdiff/config->fHVMaxDiff))){
    543           hvoltage=(unsigned int)(hvoltage + config->fHVMaxDiff*hvdiff/abs(hvdiff));
    544         }
    545         if (k==(int)(abs((int)(hvdiff/config->fHVMaxDiff)))){
    546           hvoltage=(unsigned int)(hvoltage + (hvdiff%(int)config->fHVMaxDiff));
    547         }
    548        
    549        
    550         status->HV[board][chain][channel]=hvoltage;
    551         //      printf("dac hv rampingup= %d .\n",hvoltage);
    552         if ((hv->GetHVBoard(board))->SetHV(stdout,chain,channel,hvoltage,rbuf,status->Verbose)==1) {
    553           UpdateStatus(board,rbuf);
    554           if (k==(abs((int)(hvdiff/config->fHVMaxDiff)))){
    555             sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",hv->GetHVBoard(board)->GetBoardNumber(),chain,channel,hvoltage,hvoltage,calib->DACToHV(hvoltage,hv->GetHVBoard(board)->GetBoardNumber(),chain,channel));
    556             //sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",hv->GetHVBoard(board)->GetBoardNumber(),chain,channel,hvoltage,hvoltage);
    557             DoPrompt(str);
    558             sPrintStatus(status,str,board); // Print status only to socket
    559           }
    560         }
    561         else {
    562           sprintf(str,"ERROR - board %d chain %d channel %d error: could not set hv - check timeout and try again\n",hv->GetHVBoard(board)->GetBoardNumber(), chain, channel);
    563           DoPrompt(str);
    564           errors++;
    565         }
    566       }          // for loop over k
    567       if (status->Verbose) {
    568         sPrintStatus(status,str,board);
    569         DoPrompt(str);
    570       }
    571    
    572    
    573       StartMonitor();
    574 
    575       if (errors) {
    576         sprintf(str,"ERROR - warning %d error(s)\n",errors);
    577         DoPrompt(str);
    578       }
    579       else {
    580         sprintf(str,"OK - no error(s)... success!\n");
    581         DoPrompt(str);
    582       }
    583     }
    584     else {
    585       sprintf(str,"ERROR - usage: hvdiff <PXL id> <hv difference>\n");
    586       DoPrompt(str);
    587     }
    588     return 0;
    589 
    590   }
    591 
    592       // End: Write difference of high voltage --------------------------------------------------------------------
    593  
    594 
    595 
    596   // List HV boards
    597   else if (Match(status->Param[0], "list")) {
    598    
    599     sprintf(str,"OK - %d HV board(s) active:\n",hv->GetNumberOfBoards());
    600     DoPrompt(str);
    601 
    602     for (int i=0;i<hv->GetNumberOfBoards();i++) {
    603       sprintf(str,"OK - board %d (%s)\n",(hv->GetHVBoard(i))->GetBoardNumber(),(hv->GetHVBoard(i))->GetSerial());
    604       DoPrompt(str);
    605     }
    606    
    607     return 0;
    608   }
    609 
    610 
    611   // Load HV settings from file
    612   else if (Match(status->Param[0], "load")) {
    613 
    614     char param[20][MAX_COM_SIZE];
    615     char buffer[128];
    616 
    617     int nparam  = 0;
    618     int nrows   = 0;
    619     int board   = 0;
    620     int chain   = 0;
    621     int channel = 0;
    622     int nboards = 0;
    623     int errors  = 0;
    624     unsigned int hvoltage = 0;
    625 
    626     FILE *file;
    627    
    628     if (status->Param[1][0] && !status->Param[2][0]) {
    629      
    630       if ((file=fopen((char *)Chop(status->Param[1]),"r"))!=NULL) {
    631        
    632         if (status->Verbose) {
    633           sprintf(str,"OK - file \"%s\" opened\n",Chop(status->Param[1]));
    634           DoPrompt(str);
    635         }
    636        
    637         StopMonitor();
    638 
    639         while (fgets(buffer,100,file)) {
    640          
    641           ParseInput(buffer,&nparam,param);
    642          
    643           if (nparam==2 && Match(param[0],"Device:")) {
    644                    
    645             for (int j=0;j<hv->GetNumberOfBoards();j++)
    646               if (Match(Chop(status->fUSBDevice[j]),Chop(param[1]))) {
    647 
    648                 board = j;
    649                
    650                 sprintf(str,"OK - found HV settings for board %d (%s)\n",hv->GetHVBoard(board)->GetBoardNumber(),Chop(param[1]));
    651                 DoPrompt(str);
    652                
    653                 nboards++;
    654                 nrows = 0;
    655              
    656                 while (fgets(buffer,100,file)) {
    657                  
    658                   ParseInput(buffer,&nparam,param);
    659                  
    660                   if (nparam==8) {
    661 
    662                     chain = nrows/4;
    663 
    664                     if (!((nrows)%4)) {
    665                       sprintf(str,"OK - updating board %d chain %d\n",hv->GetHVBoard(board)->GetBoardNumber(),chain);
    666                       DoPrompt(str);
    667                     }
    668 
    669                    
    670                     for (int i=0;i<nparam;i++) {
    671                      
    672                       hvoltage = atoi(param[i]);
    673                       channel  = (i+8*nrows)%32;
    674                      
    675                       // Submit HV values
    676                       if ((hv->GetHVBoard(board))->SetHV(stdout,chain,channel,hvoltage,rbuf,status->Verbose)==1) {
    677                        
    678                         status->HV[board][chain][channel]=hvoltage;
    679                         UpdateStatus(board,rbuf);
    680                        
    681                         if (status->Verbose) {
    682                           sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",
    683                                   hv->GetHVBoard(board)->GetBoardNumber(),chain,channel,hvoltage,hvoltage);
    684                           DoPrompt(str);
    685                           sPrintStatus(status,str,board);
    686                           DoPrompt(str);
    687                         }
    688                       }
    689                       else {
    690                         sprintf(str,"ERROR - board %d error: could not set HV - check timeout and try again\n",hv->GetHVBoard(board)->GetBoardNumber());
    691                         DoPrompt(str);
    692                         errors++;
    693                       }
    694                      
    695                     }
    696                    
    697                     nrows++;
    698                    
    699                   }
    700                   else if (nparam==2)
    701                     break;
    702                 }
    703               }
    704           }
    705         }
    706        
    707         if (fclose (file)) {
    708           sprintf(str,"ERROR - could not close file \"%s\"\n",Chop(status->Param[1]));
    709           DoPrompt(str);
    710         }
    711         else {
    712           if (status->Verbose) {
    713             sprintf(str,"OK - file \"%s\" closed\n",Chop(status->Param[1]));
    714             DoPrompt(str);
    715           }
    716         }
    717 
    718         if (nboards!=hv->GetNumberOfBoards()) {
    719           sprintf(str,"ERROR - warning: could not load HV settings for all connected HV boards\n");
    720           DoPrompt(str);
    721         }
    722         else {
    723           sprintf(str,"OK - success: read HV settings for all connected HV boards\n");
    724           DoPrompt(str);
    725         }
    726 
    727         if (errors) {
    728           sprintf(str,"ERROR - warning %d error(s) => check timeout and try again\n",errors);
    729           DoPrompt(str);
    730         }
    731         else {
    732           sprintf(str,"OK - no error(s)... success!\n");
    733           DoPrompt(str);
    734         }
    735        
    736       }
    737       else {
    738         sprintf(str,"ERROR - could not open file \"%s\"\n",Chop(status->Param[1]));
    739         DoPrompt(str);
    740       }
    741      
    742     }
    743     else
    744       DoPrompt("ERROR - usage: load <file>\n");
    745 
     313      } // Loop over boards
     314    } // while()
     315           
    746316    StartMonitor();
    747 
    748     return 0;
    749    
     317       
     318    if (NBoards != NumHVBoards) {
     319      PrintMessage("Warning: Could not load HV settings for all connected HV boards\n");
     320    }
     321    else if (Errors == 0) PrintMessage("Success: Read HV settings for all connected HV boards\n");
     322    if (Errors != 0) PrintMessage("Warning: Errors on %d channel(s) occurred\n", Errors);
     323   
     324    if (fclose(File) != 0) PrintMessage("Error: Could not close file '%s'\n",Param[1]);
     325
     326    return;   
    750327  }
    751328           
    752329
    753   // Enable/disable logging
    754   else if (Match(status->Param[0], "log")) {
    755 
    756     if (Match(status->Param[1], "on") && status->Param[1][0]) {
    757       status->Log = TRUE;
    758       sprintf(str,"OK - logging enabled\n");
    759       DoPrompt(str);
    760     }
    761    
    762     else if (Match(status->Param[1], "off") && status->Param[1][0]) {
    763       status->Log = FALSE;
    764       sprintf(str,"OK -logging disabled\n");
    765       DoPrompt(str);
    766     }
    767    
    768     else
    769       DoPrompt("ERROR - usage: log <on>|<off>\n");
    770  
    771     return 0;
    772   }
    773 
    774 
    775330  // Set status refresh rate
    776   if (Match(status->Param[0], "rate")) {
    777 
    778     if (!NBoards())
    779       return 0;
    780 
    781     if (status->Param[1][0]>0) {
    782 
    783       if (!IsNoDigit(status->Param[1])) {
    784         DoPrompt("ERROR - wrong input format - usage: rate <rate>\n");
    785         return 0;
    786       }
    787       // Check limits
    788       else if (atof(status->Param[1]) < MIN_RATE || atof(status->Param[1]) > MAX_RATE) {
    789         sprintf(str,"ERROR - refresh rate out of range (min: %.2f Hz, max: %.2f Hz)!\n",MIN_RATE,MAX_RATE);
    790         DoPrompt(str);
    791         return 0;
    792       }
    793       else {
    794         StopMonitor();
    795         status->fStatusRefreshRate=atof(status->Param[1]);
    796         sprintf(str,"OK - status refresh rate set to %.2f Hz\n",status->fStatusRefreshRate);
    797         DoPrompt(str);
    798       }
    799       StartMonitor();
    800       return 0;
    801      
    802     }
    803     else {
    804       sprintf(str,"ERROR - usage: rate <rate>\n");
    805       DoPrompt(str);
    806     }
    807    
    808     return 0;
    809   }
    810 
    811   /*
    812   // Read from device - NEVER use this function with a real HV board!!!
    813   if (Match(status->Param[0], "read")) {
    814 
    815     if (!NBoards())
    816       return 0;
    817 
    818     if (status->state==active) {
    819       StopMonitor();
    820       sprintf(str,"warning: status monitoring deactivated\n");
    821       DoPrompt(str);
    822     }
    823    
    824     for (int i=status->FirstBoard;i<=status->LastBoard;i++) {
    825       if (1 == ((hv->GetHVBoard(i))->Read(rbuf,1))) {
    826         sPrintByteBin(rbuf[0],bdata);
    827         sprintf(str,"%d byte(s) read (board %d): %d | 0X%.2X | B%s\n",1,i,rbuf[0],rbuf[0],bdata);
    828       }
    829       else
    830         sprintf(str,"error: could not read from board %d\n",i);
    831 
    832       usleep(1000);
    833 
    834       DoPrompt(str);
    835     }
    836 
    837     return 0;
    838   }
    839   */
     331  if (Match(Param[0], "rate")) {
     332
     333    double Rate;
     334   
     335    if (!NumHVBoards) return;
     336
     337    if (NParam != 2) {
     338      PrintMessage("Usage: rate <Hz>\n");
     339      return;
     340    }
     341   
     342    if (!ConvertToDouble(Param[1], &Rate)) {
     343       PrintMessage("Error: Wrong number format\n");
     344       return;   
     345    }
     346
     347    // Check limits
     348    if (Rate<MIN_RATE || Rate>MAX_RATE) {
     349      PrintMessage("Refresh rate out of range (min: %.2f Hz, max: %.2f Hz)\n", MIN_RATE, MAX_RATE);
     350      return;
     351    }
     352
     353    StopMonitor();
     354    fStatusRefreshRate = Rate;
     355    PrintMessage("Refresh rate set to %.2f Hz\n", fStatusRefreshRate);
     356    StartMonitor();
     357
     358    return;
     359  }
    840360 
    841361  // Reset
    842   if (Match(status->Param[0], "reset")) {
    843 
    844     if (!NBoards())
    845       return 0;
     362  if (Match(Param[0], "reset")) {
     363
     364    if (!NumHVBoards) return;
    846365
    847366    StopMonitor();
    848367    ResetActiveBoards();
    849     ReInitStatus(status);
    850368    StartMonitor();
    851     return 0;
    852   }
    853 
    854 
    855   // Start ROOT
    856   else if (Match(status->Param[0], "root")) {
    857    
    858     sprintf(str,"OK - starting ROOT... type '.q' to return\n");
    859     DoPrompt(str);
    860     system ("root");
    861 
    862   return 0;
    863  
     369    return;
    864370  }
    865371
    866372
    867373  // Save HV settings of all boards
    868   else if (Match(status->Param[0], "save")) {
    869 
    870     if (status->Param[1][0] && !status->Param[2][0]) {
    871      
    872       if (SaveHVSettings(Chop(status->Param[1]))) {
    873         sprintf(str,"OK - HV settings written to \"%s\"\n",Chop(status->Param[1]));
    874         DoPrompt(str);
     374  else if (Match(Param[0], "save")) {
     375
     376    FILE *File;
     377    time_t time_now_secs;
     378    struct tm *Time;
     379
     380    if (NParam != 2) {
     381      PrintMessage("Usage: save <Filename>\n");
     382      return;
     383    }
     384 
     385    time(&time_now_secs);
     386    Time = localtime(&time_now_secs);
     387
     388    if ((File = fopen(Param[1], "w")) == NULL) {
     389      PrintMessage("Error: Could not open file '%s' (%s)\n", Param[1], strerror(errno));
     390      return;
     391    }
     392 
     393    fprintf(File,"********** HV settings, %04d %02d %02d, %02d:%02d:%02d **********\n\n",
     394            1900 + Time->tm_year, 1 + Time->tm_mon,
     395            Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec);
     396 
     397    for (int i=0; i<NumHVBoards; i++) {
     398      fprintf(File, "%s\n\n", fHVBoard[i]->BoardName);
     399
     400      for (int j=0; j<NUM_CHAINS; j++) {
     401        for (int k=0; k<NUM_CHANNELS; k++) fprintf(File,"%5d ",fHVBoard[i]->HV[j][k]);
     402        fprintf(File, "\n");
    875403      }
    876      
    877     }
    878     else {
    879      
    880       char buffer[MAX_COM_SIZE];
    881      
    882       time_t time_now_secs;
    883       struct tm *time_now;
    884      
    885       time(&time_now_secs);
    886       time_now = localtime(&time_now_secs);
    887      
    888       sprintf(buffer,"OK - hvsettings/HV_%04d-%02d-%02d_%02d-%02d-%02d.txt",
    889               1900 + time_now->tm_year,
    890               1 + time_now->tm_mon,
    891               time_now->tm_mday,
    892               time_now->tm_hour,
    893               time_now->tm_min,
    894               time_now->tm_sec);
    895 
    896       //sprintf(str,"warning: HV settings will be written to \"%s\"\n",buffer);
    897       //DoPrompt(str);
    898      
    899       if (SaveHVSettings(buffer)) {
    900         sprintf(str,"OK - HV settings successfully written to \"%s\"\n",buffer);
    901         DoPrompt(str);
    902       }
    903     }
    904 
    905     return 0;
    906    
     404      fprintf(File, "\n");
     405    }
     406
     407    if (fclose(File) != 0) {
     408      PrintMessage("Error: Could not close file '%s' (%s)\n", Param[1], strerror(errno)); 
     409    }
     410
     411    return;
    907412  }
    908413
    909414
    910415  // Start monitoring
    911   else if (Match(status->Param[0], "start")) {
    912 
    913     if (!NBoards())
    914       return 0;
    915    
    916     if (status->state==active) {
    917       sprintf(str,"OK - status monitoring is already active\n");
    918       DoPrompt(str);
    919       return 0;
    920     }
    921 
     416  else if (Match(Param[0], "start")) {
     417
     418    if (!NumHVBoards) return;
     419   
    922420    StartMonitor();
    923 
    924     sprintf(str,"OK - status monitoring activated\n");
    925     DoPrompt(str);
    926 
    927     return 0;
    928  
     421    PrintMessage("OK - status monitoring activated\n");
     422
     423    return; 
    929424  }
    930425
    931426 
    932427  // Print status
    933   else if (Match(status->Param[0], "status") || Match(status->Param[0], "info")) {
    934    
    935     if (!NBoards())
    936       return 0;
    937 
    938     PrintStatus(status,config,stdout);
    939     PrintStatus(status,config,log->logptr);
    940 
    941     return 0;
     428  else if (Match(Param[0], "status")) {
     429   
     430    PrintMessage("\n Status monitor: %s\n", state_str[state]);
     431    PrintMessage(" Verbose: %s\n", Verbose ? "on" : "off");
     432    PrintMessage(" Status refresh rate [Hz]: %.2f\n", fStatusRefreshRate);
     433    PrintMessage(" Socket state: %s\n", Socket==-1 ? "disconnected":"connected");
     434    PrintMessage(" Total number of HV boards: %d\n", NumHVBoards);
     435    PrintMessage(" Active HV boards: %d\n\n ", LastBoard - FirstBoard + 1);
     436
     437    for (int i=FirstBoard; i<=LastBoard; i++) {
     438      PrintMessage(" BOARD %d (%s)   Wrap counter: %s (%d)  Manual reset: %s  Time-out: %.2f s\n\n",
     439        fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName,
     440        fHVBoard[i]->WrapOK ? "ok":"error",
     441        fHVBoard[i]->LastWrapCount,
     442        fHVBoard[i]->ResetButton ? "yes" : "no",
     443        fHVBoard[i]->fTimeOut);
     444
     445      for (int j=FirstChain; j<=LastChain; j++) {
     446        PrintMessage("  CHAIN %d     Over-current: %s\n ", j, fHVBoard[i]->Overcurrent[j] ? "yes" : "no");
     447        for (int k=0;k<4;k++) {
     448          for (int l=0;l<8;l++) {
     449            if(NParam == 2) PrintMessage("%5d ",fHVBoard[i]->HV[j][k*8+l]);
     450            else PrintMessage("%#5.2f ",fHVBoard[i]->HVV[j][k*8+l]);
     451          }
     452          PrintMessage("\n ");
     453        }
     454          PrintMessage("\n ");
     455      }
     456    }
     457
     458    return;
    942459  }
    943460
    944461
    945462  // Stop monitoring
    946   else if (Match(status->Param[0], "stop")) {
    947 
    948     if (!NBoards())
    949       return 0;
    950    
    951     if (status->state!=active) {
    952       sprintf(str,"OK - status monitoring is already deactivated\n");
    953       DoPrompt(str);
    954       return 0;
    955     }
    956 
    957     StopMonitor();
    958    
    959     sprintf(str,"ERROR - warning: status monitoring deactivated\n");
    960     DoPrompt(str);
    961 
    962     return 0;
    963  
    964   }
    965 
    966   /*
    967   // Sweep HV
    968   else if (Match(status->Param[0], "sweep")) {
    969 
    970     if (!NBoards())
    971       return 0;
    972 
    973     int errors = 0;
    974     int channel = 0;
    975 
    976     unsigned int hv1 = 0;
    977     unsigned int hv2 = 0;
    978     unsigned int dv  = 10;
    979 
    980     bool allchannels = FALSE;
    981 
    982     float delay = 1.;
    983 
    984     if (status->Param[1][0]>0 && status->Param[2][0]>0 && status->Param[3][0]>0 && status->Param[4][0]>0){
    985      
    986       if (status->Param[1][0] == 'a' )
    987         allchannels = TRUE;
    988       else if (IsNoDigit(status->Param[1])) {
    989         channel = atoi(status->Param[1]);
    990         // Check limits
    991         if (channel>31 || channel <0) {
    992           DoPrompt("channel out of range (0...31)!\n");
    993           return 0;
    994         }
     463  else if (Match(Param[0], "stop")) {
     464
     465    if (!NumHVBoards) return;
     466   
     467    StopMonitor();   
     468    PrintMessage("Status monitor stopped\n");
     469
     470    return;
     471  }
     472
     473
     474  // Set timeout to return from read
     475  if (Match(Param[0], "timeout")) {
     476
     477    double Timeout;
     478   
     479    if (!NumHVBoards) return;
     480
     481    if (NParam != 2) {
     482      PrintMessage("Usage: timeout <secs>\n");
     483      return;
     484    }
     485   
     486    if (!ConvertToDouble(Param[1], &Timeout)) {
     487       PrintMessage("Error: Wrong number format\n");
     488       return;   
     489    }
     490
     491    for (int i=0; i<NumHVBoards; i++) fHVBoard[i]->SetTimeOut(Timeout);
     492    PrintMessage("Timeout set to %.2f s for all boards\n", Timeout);
     493   
     494    return;
     495  }
     496
     497   
     498  // Print uptime
     499  if (Match(Param[0], "uptime")) {
     500    time_t ActualT;
     501    time (&ActualT);
     502
     503    PrintMessage("%d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60);
     504
     505    return;
     506  }
     507
     508
     509  // Enable/disable verbosity
     510  else if (Match(Param[0], "verbose")) {
     511
     512    if (Match(Param[1], "on")) {
     513      Verbose = true;
     514      PrintMessage("Verbosity enabled\n");
     515    }   
     516    else if (Match(Param[1], "off")) {
     517      Verbose = false;
     518      PrintMessage("Verbosity disabled\n");
     519    }
     520    else PrintMessage("Usage: verbose <on>|<off>\n");
     521 
     522    return;
     523  }
     524 
     525 
     526  // Exit program
     527  else if(Match(Param[0], "exit")) {
     528
     529    if (CmdFromSocket) {
     530      PrintMessage("Exit command not allowed over socket.\n");
     531      return;
     532    }   
     533
     534    Exit = true;
     535    pthread_kill(HVMonitor, SIGUSR1);
     536    pthread_kill(SocketThread, SIGUSR1);
     537 
     538    return;
     539  }
     540 
     541  PrintMessage("Unknown command '%s'\n", Param[0]);
     542 
     543  return;
     544}
     545
     546
     547// Print message to selected target
     548void ProcessIO::PrintMessage(int Target, const char *Format, ...) {
     549  va_list ArgumentPointer;
     550  va_start(ArgumentPointer, Format);
     551  PrintMessage(Target, Format, ArgumentPointer);
     552  va_end(ArgumentPointer);
     553}
     554
     555// Print message to log file, and screen or socket (depending on command origin)
     556void ProcessIO::PrintMessage(const char *Format, ...) {
     557  va_list ArgumentPointer;
     558  va_start(ArgumentPointer, Format);
     559  if (CmdFromSocket) PrintMessage(MsgToSocket|MsgToLog, Format, ArgumentPointer);
     560  else PrintMessage(MsgToConsole|MsgToLog, Format, ArgumentPointer);
     561  va_end(ArgumentPointer);
     562}
     563
     564// Function doing the actual printing work
     565void ProcessIO::PrintMessage(int Target, const char *Format, va_list ArgumentPointer) {
     566
     567  char Textbuffer[MAX_COM_SIZE];
     568
     569  memset(Textbuffer, 0, sizeof(Textbuffer)); 
     570  vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer);
     571 
     572  // Print to console
     573  if(Target & MsgToConsole) {
     574    if(strlen(Textbuffer)>0 && Textbuffer[strlen(Textbuffer)-1]=='\n') {
     575      printf("\r%s%s", Textbuffer, Prompt);   // New prompt
     576      fflush(stdout);
     577    }
     578    else printf("%s", Textbuffer);
     579  }
     580  // Print to log file
     581  if((Target & MsgToLog) && Logfile!=NULL) {
     582    fprintf(Logfile, "%s", Textbuffer);
     583    fflush(Logfile);
     584  }
     585  // Print to socket
     586  if((Target & MsgToSocket) && Socket!=-1) {
     587    write(Socket, Textbuffer, strlen(Textbuffer));
     588  }
     589}
     590
     591
     592// Ramp to new voltage with maximum step size given in config->fHVMaxDiff
     593// No ramping when decreasing voltage
     594bool ProcessIO::RampVoltage(unsigned int Target, int Board, int Chain, int Channel) {
     595
     596  int Diff;
     597 
     598  while (fHVBoard[Board]->HV[Chain][Channel] != (int) Target) {   
     599    Diff = Target - fHVBoard[Board]->HV[Chain][Channel];
     600    if (Diff > (int) config->fHVMaxDiff) Diff = config->fHVMaxDiff;
     601
     602    if (fHVBoard[Board]->SetHV(stdout, Chain, Channel, fHVBoard[Board]->HV[Chain][Channel]+Diff, Verbose)==1) {
     603      fHVBoard[Board]->HV[Chain][Channel] += Diff;
     604
     605      if (Verbose) {
     606        PrintMessage("OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",fHVBoard[Board]->GetBoardNumber(),Chain, Channel, Target, Target, calib->DACToHV(Target,fHVBoard[Board]->GetBoardNumber(),Chain,Channel));
     607        PrintBoardStatus(Board);
    995608      }
    996      
    997       if (IsNoDigit(status->Param[2]) && IsNoDigit(status->Param[3]) && IsNoDigit(status->Param[4])) {
    998        
    999         hv1 = atoi(status->Param[2]);
    1000         hv2 = atoi(status->Param[3]);
    1001         dv  = atoi(status->Param[4]);
    1002        
    1003         if ((hv1>0X3FFF || hv1 <0) || (hv2>0X3FFF || hv2 <0)) {
    1004           DoPrompt("high voltage out of range (Vmin: 0, Vmax: 16383)!\n");
    1005           return 0;
    1006         }
    1007 
    1008         if (hv1 > hv2) {
    1009           DoPrompt("wrong limits (Vmin < Vmax)!\n");
    1010           return 0;
    1011         }
    1012 
    1013         if (dv < 1 || dv > abs(hv2-hv1)) {
    1014           DoPrompt("step size out of range (dVmin: 1, dVmax: |hv2-hv1|)!\n");
    1015           return 0;
    1016         }
    1017        
    1018         if (status->Param[5][0]>0 && IsNoDigit(status->Param[5])) {
    1019           if (atof(status->Param[5])<MIN_SWEEP_RATE || atof(status->Param[5])>MAX_SWEEP_RATE) {
    1020             sprintf(str,"rate out of range (min: %.2f Hz, max: %.2f Hz)!\n",MIN_SWEEP_RATE,MAX_SWEEP_RATE);         
    1021             DoPrompt(str);
    1022             return 0;
    1023           }
    1024           else
    1025             delay = 1./atof(status->Param[5]);
    1026         }
     609    }
     610    else {
     611      PrintMessage("ERROR - Could not set HV of board %d, chain %d, channel %d. Skipping channel\n",fHVBoard[Board]->GetBoardNumber(),Chain,Channel);
     612      return false;
     613    }
     614  }
     615  return true;
     616}
     617
     618void ProcessIO::StartMonitor() {
     619
     620  state = active;
     621  pthread_kill(HVMonitor, SIGUSR1);
     622}
     623
     624
     625void ProcessIO::StopMonitor() {
     626
     627  state = stopped;
     628  pthread_kill(HVMonitor, SIGUSR1);
     629}
     630
     631
     632void ProcessIO::Monitor() {
     633
     634  for (int i=0; i<NumHVBoards; i++) {
     635
     636    if (fHVBoard[i]->GetStatus(stdout,false)!=1) {
     637      PrintMessage("Error: Monitor, could not read status of board %d\n", fHVBoard[i]->GetBoardNumber());
     638    }
     639   
     640    if (fHVBoard[i]->ResetButton) {
     641      PrintMessage("Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber());
     642      ResetBoard(i);
     643    }
     644   
     645    if (!fHVBoard[i]->WrapOK) {
     646      PrintMessage("Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber());
     647    }
     648
     649    for (int j=0; j<NUM_CHAINS; j++) {
     650      if (fHVBoard[i]->Overcurrent[j]) {
     651        PrintMessage("Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber());
     652        ResetBoard(i);
    1027653      }
    1028       else {
    1029         DoPrompt("error: wrong input format - usage: sweep <channel>|<all> <v1> <v2> <dv> [rate]\n");
    1030         return 0;
    1031       }
    1032 
    1033 
    1034       StopMonitor();
    1035      
    1036       for (int i=status->FirstBoard;i<=status->LastBoard;i++)
    1037         for (int j=status->FirstChain;j<=status->LastChain;j++) {
    1038           if (!allchannels) {
    1039            
    1040             for (unsigned int v = hv1; v<=hv2; v+=dv) {
    1041               if ((hv->GetHVBoard(i))->SetHV(stdout,j,channel,v,rbuf,status->Verbose)==1) {
    1042                 sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",i,j,channel,v,v);
    1043                 status->HV[i][j][channel]=v;
    1044                 DoPrompt(str);
    1045                 UpdateStatus(i,rbuf);
    1046                 sPrintStatus(status,str,i);
    1047                 DoPrompt(str);
    1048               }
    1049               else {
    1050                 sprintf(str,"board %d error: could not set hv - check timeout and try again\n",i);
    1051                 DoPrompt(str);
    1052                 errors++;
    1053               }
    1054 
    1055               usleep((unsigned long)floor(delay*1000000.));
    1056             }
    1057 
    1058           }
    1059           else {
    1060             for (int k=0;k<MAX_NUM_CHANNELS;k++) {
    1061 
    1062               for (unsigned int v = hv1; v<=hv2; v+=dv) {
    1063                
    1064                 if ((hv->GetHVBoard(i))->SetHV(stdout,j,k,v,rbuf,status->Verbose)==1) {
    1065                   sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",i,j,k,v,v);
    1066                   status->HV[i][j][k]=v;
    1067                   DoPrompt(str);
    1068                   UpdateStatus(i,rbuf);
    1069                   sPrintStatus(status,str,i);
    1070                   DoPrompt(str);
    1071                 }
    1072                 else {
    1073                   sprintf(str,"board %d error: could not set hv - check timeout and try again\n",i);
    1074                   DoPrompt(str);
    1075                   errors++;
    1076                 }
    1077                
    1078                 usleep((unsigned long)floor(delay*1000000.));
    1079 
    1080               }
    1081             }
    1082           }
    1083         }
    1084 
    1085       StartMonitor();
    1086 
    1087       if (errors) {
    1088         sprintf(str,"warning %d error(s) => check timeout and try again\n",errors);
    1089         DoPrompt(str);
    1090       }
    1091       else {
    1092         sprintf(str,"no error(s)... success!\n");
    1093         DoPrompt(str);
    1094       }
     654    }
     655  }
     656}
     657
     658
     659void ProcessIO::ResetActiveBoards() {
     660 
     661  for (int i=FirstBoard; i<=LastBoard; i++) ResetBoard(i);
     662}
     663
     664
     665void ProcessIO::ResetBoard(int i) {
     666   
     667  if (fHVBoard[i]->Reset(stdout,Verbose) == 1) {
     668    PrintMessage("Reset of board %d\n", fHVBoard[i]->GetBoardNumber());
     669    PrintBoardStatus(i);
     670  }
     671  else PrintMessage("Error: Could not reset board %d\n",fHVBoard[i]->GetBoardNumber());
     672}
     673
     674
     675int ProcessIO::GetBoardIdx(int board) {
     676
     677  for (int i=0; i<MAX_NUM_HVBOARDS; i++) {
     678    if (board == fHVBoard[i]->GetBoardNumber()) return i;
     679  }
     680  return -1;
     681}
     682
     683
     684void ProcessIO::PrintBoardStatus(int i) {
     685
     686  PrintMessage("Status board %d (%s): MR %s OC0 %s OC1 %s OC2 %s OC3 %s WC %s (%d)\n",
     687          fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName,
     688          fHVBoard[i]->ResetButton ? "yes" : "no",
     689          fHVBoard[i]->Overcurrent[0] ? "yes" : "no",
     690          fHVBoard[i]->Overcurrent[1] ? "yes" : "no",
     691          fHVBoard[i]->Overcurrent[2] ? "yes" : "no",
     692          fHVBoard[i]->Overcurrent[3] ? "yes" : "no",
     693          fHVBoard[i]->WrapOK ? "ok":"error", fHVBoard[i]->LastWrapCount);
     694}
     695
     696
     697// Parse command line for white space and double-quote separated tokens
     698int ProcessIO::ParseInput(char* Command, const char *Param[]) {
     699  int Count=0;
     700   
     701  while(Count<MAX_NUM_TOKEN) {
     702    while (isspace(*Command)) Command++; // Ignore initial white spaces
     703    if(*Command=='\0') break;
     704    if (*Command == '\"') {
     705      Param[Count] = ++Command;
     706      while(*Command!='\"' && *Command!='\0') Command++;
    1095707    }
    1096708    else {
    1097       DoPrompt("usage: sweep <channel>|<all> <v1> <v2> <dv> [rate]\n");
    1098       return 0;
    1099     }
    1100    
    1101     return 0;
    1102  
    1103   }
    1104   */
    1105 
    1106   // Print time and date
    1107   else if (Match(status->Param[0], "date") || Match(status->Param[0], "time")) {
    1108 
    1109     PrintDateAndTime();
    1110    
    1111     return 0;
    1112   }
    1113 
    1114 
    1115   /*
    1116   // Test I/O - NEVER use this function with a real HV board!!!
    1117   else if (Match(status->Param[0], "testio")) {
    1118 
    1119     for (int i=status->FirstBoard;i<=status->LastBoard;i++)
    1120       (hv->GetHVBoard(i))->TestIO();
    1121 
    1122     return 0;
    1123   }
    1124   */
    1125 
    1126 
    1127   // Set timeout to return from read
    1128   if (Match(status->Param[0], "timeout")) {
    1129 
    1130     if (!NBoards())
    1131       return 0;
    1132 
    1133     if (status->Param[1][0]>0) {
    1134 
    1135       if (!IsNoDigit(status->Param[1])) {
    1136         DoPrompt("ERROR - wrong input format - usage: timeout <time>\n");
    1137         return 0;
    1138       }
    1139       // Check limits
    1140       else if (atof(status->Param[1]) < MIN_TIMEOUT || atof(status->Param[1]) > MAX_TIMEOUT) {
    1141         sprintf(str,"ERROR -timeout out of range (min: %.2f s, max: %.2f s)!\n",MIN_TIMEOUT,MAX_TIMEOUT);
    1142         DoPrompt(str);
    1143         return 0;
    1144       }
    1145       else {
    1146         StopMonitor(); 
    1147         for (int i=0;i<hv->GetNumberOfBoards();i++)
    1148           (hv->GetHVBoard(i))->SetTimeOut((float)atof(status->Param[1]));
    1149         status->fTimeOut = atof(status->Param[1]);     
    1150         sprintf(str,"OK - timeout set to %.2f s\n",status->fTimeOut);
    1151 
    1152         DoPrompt(str);
    1153        
    1154         StartMonitor();
    1155         return 0;
    1156       }
    1157     }
    1158     else {
    1159       sprintf(str,"ERROR - usage: timeout <time>\n");
    1160       DoPrompt(str);
    1161     }
    1162    
    1163     return 0;
    1164   }
    1165 
    1166    
    1167   // Print uptime
    1168   if (Match(status->Param[0], "uptime")) {
    1169 
    1170     double difftime = GetDiffTime(&StartTime);
    1171 
    1172     sprintf(str,"OK - %d:%02d:%02d\n",(int)difftime/SECONDS_HOUR,((int)difftime/SECONDS_MINUTE)%SECONDS_MINUTE,(int)difftime%SECONDS_MINUTE);
    1173     DoPrompt(str);
    1174 
    1175     return 0;
    1176   }
    1177 
    1178 
    1179   // Enable/disable verbosity
    1180   else if (Match(status->Param[0], "verbose")) {
    1181 
    1182     if (Match(status->Param[1], "on") && status->Param[1][0]) {
    1183       if (status->Verbose == TRUE) {
    1184         sprintf(str,"OK - verbosity is already enabled\n");
    1185         DoPrompt(str);
    1186       }
    1187       else {
    1188         status->Verbose = TRUE;
    1189         sprintf(str,"OK - verbosity enabled\n");
    1190         DoPrompt(str);
    1191       }
    1192     }
    1193    
    1194     else if (Match(status->Param[1], "off") && status->Param[1][0]) {
    1195       if (status->Verbose == FALSE) {
    1196         sprintf(str,"OK - verbosity is already disabled\n");
    1197         DoPrompt(str);
    1198       }
    1199       else {
    1200         status->Verbose = FALSE;
    1201         sprintf(str,"OK - verbosity disabled\n");
    1202         DoPrompt(str);
    1203       }
    1204     }
    1205    
    1206     else
    1207       DoPrompt("ERROR - usage: verbose <on>|<off>\n");
    1208  
    1209     return 0;
    1210   }
    1211  
    1212  
    1213   // Write reference voltage
    1214   if (Match(status->Param[0], "vref")) {
    1215 
    1216     if (!NBoards())
    1217       return 0;
    1218 
    1219     unsigned int voltage = 0;
    1220 
    1221     if (status->Param[1][0]>0) {
    1222      
    1223       // Binary input
    1224       if (tolower(status->Param[1][0])=='x' && strlen(status->Param[1])>2) {
    1225         if (sPrintHex2Dec(Chop(status->Param[1]+1),&voltage)!=0) {
    1226             DoPrompt("ERROR - wrong input format - usage: vref <voltage>\n");
    1227             return 0;
    1228         }
    1229       }
    1230       // Hexadecimal input
    1231       else if (tolower(status->Param[1][0])=='b' && strlen(status->Param[1])>2) {
    1232         if (sPrintBin2Dec(Chop(status->Param[1]+1),&voltage)!=0) {
    1233           DoPrompt("ERROR - wrong input format - usage: vref <voltage>\n");
    1234           return 0;
    1235         }
    1236       }
    1237       // Decimal input
    1238       else if (IsNoDigit(status->Param[1]))
    1239         voltage = atoi(status->Param[1]);
    1240       // Wrong input format
    1241       else {
    1242         DoPrompt("ERROR - wrong input format - usage: vref <voltage>\n");
    1243         return 0;
    1244       }
    1245 
    1246       // Check limits
    1247       if (voltage>0X3FFF || voltage <0) {
    1248         DoPrompt("ERROR - reference voltage out of range (Vmin: 0, Vmax: 16383)!\n");
    1249         return 0;
    1250       }
    1251 
    1252 
    1253       StopMonitor();
    1254          
    1255       for (int i=status->FirstBoard;i<=status->LastBoard;i++)
    1256         for (int j=status->FirstChain;j<=status->LastChain;j++) {
    1257           if (((hv->GetHVBoard(i))->SetVRef(stdout,j,voltage,rbuf,status->Verbose)==1)) {
    1258             sprintf(str,"OK - board %d: reference voltage of chain %d set to %d | 0X%.4X\n",hv->GetHVBoard(i)->GetBoardNumber(),j,voltage,voltage);
    1259             status->VRef[i][j]=voltage;
    1260             DoPrompt(str);
    1261             UpdateStatus(i,rbuf);
    1262             sPrintStatus(status,str,i);
    1263             DoPrompt(str);
    1264           } else {
    1265             sprintf(str,"ERROR - board %d error: could not set vref - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber());
    1266             DoPrompt(str);
    1267           }
    1268         }
    1269      
    1270       StartMonitor();
    1271     }
    1272     else {
    1273       sprintf(str,"ERROR - usage: vref <voltage>\n");
    1274       DoPrompt(str);
    1275     }
    1276 
    1277     return 0;
    1278   }
    1279 
    1280   /*
    1281   // Write to device - NEVER use this function with a real HV board!!!
    1282   if (Match(status->Param[0], "write")) {
    1283    
    1284     if (!NBoards())
    1285       return 0;
    1286 
    1287     if (status->Param[1][0]>0) {
    1288      
    1289       // Binary input
    1290       if (tolower(status->Param[1][0])=='x' && strlen(status->Param[1])>2) {
    1291         if (sPrintHex2Dec(Chop(status->Param[1]+1),(unsigned int*)wbuf)!=0) {
    1292           DoPrompt("wrong input format or value out of range!\n");
    1293           return 0;
    1294         }
    1295       }
    1296       // Hexadecimal input
    1297       else if (tolower(status->Param[1][0])=='b' && strlen(status->Param[1])>2) {
    1298         if (sPrintBin2Dec(Chop(status->Param[1]+1),(unsigned int*)wbuf)!=0) {
    1299           DoPrompt("wrong input format or value out of range!\n");
    1300           return 0;
    1301         }
    1302       }
    1303       // Decimal input
    1304       else if (atoi(status->Param[1])>=0 && atoi(status->Param[1])<=255 && IsNoDigit(status->Param[1]))
    1305         wbuf[0] = (unsigned char)atoi(status->Param[1]);
    1306       // Wrong input
    1307       else {
    1308         DoPrompt("wrong input format or value out of range!\n");
    1309         return 0;
    1310       }
    1311      
    1312       if (status->state==active) {
    1313         StopMonitor();
    1314         sprintf(str,"warning: status monitoring deactivated\n");
    1315         DoPrompt(str);
    1316       }
    1317      
    1318       for (int i=status->FirstBoard;i<=status->LastBoard;i++)
    1319         if ((hv->GetHVBoard(i))->Write(wbuf,1) == 1) {
    1320           sPrintByteBin(wbuf[0],bdata);
    1321           sprintf(str,"%d byte(s) written (board %d): %d | 0X%.2X | B%s\n",1,i,wbuf[0],wbuf[0],bdata);
    1322           DoPrompt(str);
    1323         }
    1324         else {
    1325           sprintf(str,"error: could not write to board %d\n",i);
    1326           DoPrompt(str);
    1327         }
    1328 
    1329     }
    1330     else {
    1331       sprintf(str,"error: no input\n");
    1332       DoPrompt(str);
    1333     }
    1334     return 0;
    1335   }
    1336   */
    1337 
    1338   // Exit program
    1339   else if(Match(status->Param[0], "exit") || Match(status->Param[0], "quit")) {
    1340 
    1341     StopMonitor();
    1342    
    1343     ResetAllBoards();
    1344 
    1345     status->Exit = TRUE;
    1346 
    1347     pthread_kill(status->HVMonitor, SIGUSR1);
    1348     pthread_kill(status->SocketThread, SIGUSR1);
    1349  
    1350     return 0;
    1351   }
    1352  
    1353   else if (strchr(status->Param[0],'\n')-status->Param[0]==0) {
    1354     return 0;
    1355   }
    1356 
    1357   else {
    1358    
    1359     if (strchr(status->Param[0],'\n') == 0)
    1360       sprintf(str,"ERROR - unknown command: %s\n",status->Param[0]);
    1361     else
    1362       sprintf(str,"ERROR - unknown command: %s",status->Param[0]);
    1363    
    1364     DoPrompt(str);
    1365    
    1366     return 0;
    1367 
    1368   }
    1369  
    1370   return 0;
    1371 }
    1372 
    1373 
    1374 void ProcessIO::PrintDateAndTime() {
    1375 
    1376   char str[MAX_COM_SIZE];
    1377 
    1378   time_t rawtime;
    1379   struct tm * timeinfo;
    1380  
    1381   time(&rawtime);
    1382   timeinfo = localtime(&rawtime); // Get local time
    1383   fflush(stdout);
    1384   sprintf(str,"OK - current date/time is: %s",asctime(timeinfo));
    1385   DoPrompt(str);
    1386 
    1387 }
    1388 
    1389 void ProcessIO::DoPrompt(char* str) {
    1390   if (str!=NULL) {
    1391     if (status->Socket != -1) // Print status string to socket if open
    1392       write(status->Socket,str,strlen(str)+1);
    1393   }
    1394   else {
    1395     if (status->Socket != -1) // Print status string to socket if open
    1396       write(status->Socket,"OK\n",3);
    1397   }
    1398   if (str!=NULL) {
    1399     if (status->NumHVBoards == 0) {
    1400       sprintf(status->Prompt,"HV> %s",str);
    1401       printf(status->Prompt);
    1402       if (status->Log)
    1403         log->LogWrite(status->Prompt);
    1404       sprintf(status->Prompt,"HV> ");
    1405     }
    1406     else if (status->FirstBoard == status->LastBoard) {
    1407 
    1408       int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1409 
    1410       if (status->FirstChain == status->LastChain) {
    1411         sprintf(status->Prompt,"HV|C%d|B%d> %s",status->FirstChain,board,str);
    1412         printf(status->Prompt);
    1413         if (status->Log)
    1414           log->LogWrite(status->Prompt);
    1415         sprintf(status->Prompt,"HV|C%d|B%d> ",status->FirstChain,board);
    1416       }
    1417       else {
    1418         sprintf(status->Prompt,"HV|C%d-%d|B%d> %s",status->FirstChain,status->LastChain,board,str);
    1419         printf(status->Prompt);
    1420         if (status->Log)
    1421           log->LogWrite(status->Prompt);
    1422         sprintf(status->Prompt,"HV|C%d-%d|B%d> ",status->FirstChain,status->LastChain,board);
    1423       }
    1424 
    1425     }
    1426     else {
    1427      
    1428       int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1429         hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1430 
    1431       int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1432         hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber();
    1433 
    1434       if (status->FirstChain == status->LastChain) {
    1435         sprintf(status->Prompt,"HV|C%d|B%d-%d> %s",status->FirstChain,firstboard,lastboard,str);
    1436         printf(status->Prompt);
    1437         if (status->Log)
    1438           log->LogWrite(status->Prompt);
    1439         sprintf(status->Prompt,"HV|C%d|B%d-%d> ",status->FirstChain,firstboard,lastboard);
    1440       }
    1441       else {
    1442         sprintf(status->Prompt,"HV|C%d-%d|B%d-%d> %s",status->FirstChain,status->LastChain,firstboard,lastboard,str);
    1443         printf(status->Prompt);
    1444         if (status->Log)
    1445           log->LogWrite(status->Prompt);
    1446         sprintf(status->Prompt,"HV|C%d-%d|B%d-%d> ",status->FirstChain,status->LastChain,firstboard,lastboard);
    1447       }
    1448     }
    1449   }
    1450   else {
    1451     if (status->NumHVBoards == 0)
    1452       sprintf(status->Prompt,"HV> ");
    1453     else if (status->FirstBoard == status->LastBoard) {
    1454      
    1455       int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1456 
    1457       if (status->FirstChain == status->LastChain)
    1458         sprintf(status->Prompt,"HV|C%d|B%d> ",status->FirstChain,board);
    1459       else
    1460         sprintf(status->Prompt,"HV|C%d-%d|B%d> ",status->FirstChain,status->LastChain,board);
    1461     }
    1462     else {
    1463 
    1464       int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1465         hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1466 
    1467       int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1468         hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber();
    1469 
    1470      if (status->FirstChain == status->LastChain)
    1471        sprintf(status->Prompt,"HV|C%d|B%d-%d> ",status->FirstChain,firstboard,lastboard);
    1472      else
    1473        sprintf(status->Prompt,"HV|C%d-%d|B%d-%d> ",status->FirstChain,status->LastChain,firstboard,lastboard);
    1474      }
    1475   }
    1476 }
    1477 
    1478 
    1479 void ProcessIO::PrintMessage(char *str) {
    1480 
    1481   char outstr[MAX_COM_SIZE];
    1482  
    1483   fflush(stdout);
    1484   if (str!=NULL) {
    1485 
    1486     if (status->NumHVBoards == 0)
    1487       sprintf(outstr,"%s\nHV> ",str);
    1488     else if (status->FirstBoard == status->LastBoard) {
    1489      
    1490       int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1491      
    1492       if (status->FirstChain == status->LastChain)
    1493         sprintf(outstr,"%s\nHV|C%d|B%d> ",str,status->FirstChain,board);
    1494       else
    1495         sprintf(outstr,"%s\nHV|C%d-%d|B%d> ",str,status->FirstChain,status->LastChain,board);
    1496     }
    1497     else {
    1498      
    1499       int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1500         hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1501      
    1502       int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1503         hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber();
    1504      
    1505       if (status->FirstChain == status->LastChain)
    1506         sprintf(outstr,"%s\nHV|C%d|B%d-%d> ",str,status->FirstChain,firstboard,lastboard);
    1507       else
    1508         sprintf(outstr,"%s\nHV|C%d-%d|B%d-%d> ",str,status->FirstChain,status->LastChain,firstboard,lastboard);
    1509     }
    1510   }
    1511   else {
    1512 
    1513     if (status->NumHVBoards == 0)
    1514       sprintf(outstr,"HV> ");
    1515     else if (status->FirstBoard == status->LastBoard) {
    1516      
    1517       int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1518      
    1519       if (status->FirstChain == status->LastChain)
    1520         sprintf(outstr,"HV|C%d|B%d> ",status->FirstChain,board);
    1521       else
    1522         sprintf(outstr,"HV|C%d-%d|B%d> ",status->FirstChain,status->LastChain,board);
    1523     }
    1524     else {
    1525      
    1526       int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1527         hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1528      
    1529       int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1530         hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber();
    1531      
    1532       if (status->FirstChain == status->LastChain)
    1533         sprintf(outstr,"HV|C%d|B%d-%d> ",status->FirstChain,firstboard,lastboard);
    1534       else
    1535         sprintf(outstr,"HV|C%d-%d|B%d-%d> ",status->FirstChain,status->LastChain,firstboard,lastboard);
    1536     }
    1537 
    1538 
    1539   }
    1540 
    1541   fflush(stdout);
    1542   fputs(outstr, stdout);
    1543   fflush(stdout);
    1544 
    1545 }
    1546 
    1547 
    1548 void ProcessIO::PrintMessageToLog(char *str) {
    1549 
    1550   char outstr[MAX_COM_SIZE];
    1551 
    1552   if (status->NumHVBoards == 0) {
    1553     sprintf(outstr,"HV|B> %s\n",str);
    1554     log->LogWrite(outstr);
    1555   }
    1556   else if (status->FirstBoard == status->LastBoard) {
    1557    
    1558     int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1559    
    1560     sprintf(outstr,"HV|B%d> %s\n",board,str);
    1561     log->LogWrite(outstr);
    1562   }
    1563   else {
    1564    
    1565     int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1566       hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber();
    1567    
    1568     int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ?
    1569       hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber();
    1570 
    1571     sprintf(outstr,"HV|B%d-%d> %s\n",firstboard,lastboard,str);
    1572    log->LogWrite(outstr);
    1573   }
    1574 
    1575 }
    1576 
    1577 
    1578 // Print message to screen, log file and socket
    1579 void ProcessIO::PrintMessageO(char *Format, ...) {
    1580 
    1581   char Textbuffer[MAX_COM_SIZE];
    1582 
    1583   va_list ArgumentPointer;  va_start(ArgumentPointer, Format);
    1584   vsprintf(Textbuffer, Format, ArgumentPointer);
    1585 
    1586   fputs(Textbuffer, stdout);   fflush(stdout);  // Print to console
    1587  
    1588   if(status->Socket != -1)                      // Print to socket if open
    1589     write(status->Socket,Textbuffer,strlen(Textbuffer)+1); // +1 to transmit '\0'
    1590 }
    1591 
    1592 
    1593 int ProcessIO::NBoards() {
    1594 
    1595   if (status->NumHVBoards==0)
    1596     DoPrompt("ERROR - no HV boards available!\n");
    1597 
    1598   return status->NumHVBoards;
    1599 }
    1600 
    1601 
    1602 int ProcessIO::InitializeHV() {
    1603 
    1604   int nb = 0;
    1605 
    1606   if (hv->GetNumberOfBoards())
    1607     printf("OK - Initialization:\n");
    1608 
    1609   for (int i=0;i<hv->GetNumberOfBoards();i++) {
    1610     printf("OK - HV board %d (%s):\n",hv->GetHVBoard(i)->GetBoardNumber(),hv->GetHVBoard(i)->GetSerial());
    1611     nb+=hv->GetHVBoard(i)->Init(status->Verbose);
    1612   }
    1613 
    1614   return nb;
    1615 }
    1616 
    1617 
    1618 void ProcessIO::UpdateStatus(int i, unsigned char* rbuf) {
    1619 
    1620   if (status->IsUpdated[i])
    1621     status->WC[0][i] = status->WC[1][i];
    1622   else {
    1623     status->WC[0][i] = hv->GetHVBoard(i)->DecodeWrap(rbuf)-1;
    1624     status->IsUpdated[i] = TRUE;
    1625   }
    1626  
    1627   status->WC[1][i] = hv->GetHVBoard(i)->DecodeWrap(rbuf);
    1628 
    1629   int d = (int)abs(status->WC[0][i]-status->WC[1][i]);
    1630 
    1631   status->isok[i] = (d==1 || d==7) ? 1 : 0;
    1632 
    1633   hv->GetHVBoard(i)->DecodeOC(status->OC[i], rbuf);
    1634   status->MR[i] = hv->GetHVBoard(i)->DecodeReset(rbuf);
    1635 
    1636 }
    1637 
    1638 
    1639 void ProcessIO::StartMonitor() {
    1640 
    1641   status->state = active;
    1642   status->Stop  = FALSE;
    1643 
    1644   pthread_kill(status->HVMonitor, SIGUSR1);
    1645 
    1646 }
    1647 
    1648 
    1649 void ProcessIO::StopMonitor() {
    1650 
    1651   status->state = stopped;
    1652   status->Stop  = TRUE;
    1653 
    1654   pthread_kill(status->HVMonitor, SIGUSR1);
    1655 
    1656 }
    1657 
    1658 
    1659 void ProcessIO::Monitor() {
    1660 
    1661   char str[MAX_COM_SIZE];
    1662 
    1663   for (int i=0;i<hv->GetNumberOfBoards() ;i++) {
    1664 
    1665     if ((hv->GetHVBoard(i))->GetStatus(stdout,rbuf,FALSE)!=1) {
    1666       sprintf(str,"ERROR - board %d error: could not read status - check timeout and status refresh rate...",hv->GetHVBoard(i)->GetBoardNumber());
    1667       PrintMessage(str);     
    1668     }
    1669     else
    1670       UpdateStatus(i,rbuf);
    1671    
    1672     if (status->MR[i]) {
    1673       sprintf(str,"ERROR - warning: manual reset of board %d!",hv->GetHVBoard(i)->GetBoardNumber());
    1674       PrintMessage(str);     
    1675       StopMonitor();
    1676       ResetBoard(i);
    1677       ReInitStatusOneBoard(status,i);
    1678       StartMonitor();
    1679     }
    1680    
    1681     if (!status->isok[i]) {
    1682       sprintf(str,"ERROR - wrap counter mismatch board %d (%d,%d)!",hv->GetHVBoard(i)->GetBoardNumber(),status->WC[0][i],status->WC[1][i]);
    1683       PrintMessage(str);     
    1684     }
    1685 
    1686     for (int j=0;j<MAX_NUM_CHAINS;j++)
    1687       if (status->OC[i][j]) {
    1688         sprintf(str,"ERROR - warning: overcurrent in chain %d of board %d!",j,hv->GetHVBoard(i)->GetBoardNumber());
    1689         PrintMessage(str);     
    1690         ResetBoard(i);
    1691         ReInitStatusOneBoard(status,i);
    1692       }
    1693   }
    1694 }
    1695 
    1696 
    1697 void ProcessIO::ResetActiveBoards() {
    1698  
    1699   for (int i=status->FirstBoard;i<=status->LastBoard;i++) {
    1700     if ((hv->GetHVBoard(i))->Reset(stdout,rbuf,status->Verbose)==1) {
    1701       sprintf(str,"OK - software reset done board %d\n",hv->GetHVBoard(i)->GetBoardNumber());
    1702       DoPrompt(str);
    1703       UpdateStatus(i,rbuf);
    1704       sPrintStatus(status,str,i);
    1705       DoPrompt(str);
    1706     }
    1707     else {
    1708       sprintf(str,"ERROR - board %d error: could not reset - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber());
    1709         DoPrompt(str);
    1710     }   
    1711   }
    1712  
    1713 }
    1714 
    1715 
    1716 void ProcessIO::ResetAllBoards() {
    1717  
    1718   for (int i=0;i<hv->GetNumberOfBoards();i++) {
    1719     if ((hv->GetHVBoard(i))->Reset(stdout,rbuf,status->Verbose)==1) {
    1720       sprintf(str,"OK - software reset done board %d\n",hv->GetHVBoard(i)->GetBoardNumber());
    1721       DoPrompt(str);
    1722       UpdateStatus(i,rbuf);
    1723       sPrintStatus(status,str,i);
    1724       DoPrompt(str);
    1725     }
    1726     else {
    1727       sprintf(str,"ERROR - board %d error: could not reset - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber());
    1728       DoPrompt(str);
    1729     }   
    1730   }
    1731  
    1732 }
    1733 
    1734 
    1735 void ProcessIO::ResetBoard(int i) {
    1736    
    1737   if ((hv->GetHVBoard(i))->Reset(stdout,rbuf,status->Verbose)==1) {
    1738     sprintf(str,"OK - software reset done board %d",hv->GetHVBoard(i)->GetBoardNumber());
    1739     PrintMessage(str);
    1740     UpdateStatus(i,rbuf);
    1741     sPrintStatus(status,str,i);
    1742     PrintMessage(Chop(str));
    1743   }
    1744   else {
    1745     sprintf(str,"ERROR - board %d error: could not reset - check timeout and try again",hv->GetHVBoard(i)->GetBoardNumber());
    1746     PrintMessage(str);
    1747   }   
    1748  
    1749 }
    1750 
    1751 
    1752 int ProcessIO::SaveHVSettings(char* filename) {
    1753 
    1754   char str[MAX_COM_SIZE];
    1755 
    1756   FILE *fptr;
    1757 
    1758   time_t time_now_secs;
    1759   struct tm *time_now;
    1760  
    1761   time(&time_now_secs);
    1762   time_now = localtime(&time_now_secs);
    1763 
    1764   if ((fptr = fopen(filename,"w")) == NULL) {
    1765     sprintf(str,"ERROR - could not open file \"%s\"\n", filename);
    1766     return 0;
    1767   }
    1768  
    1769   fprintf(fptr,"\n********** HV settings written by hvutil %s, %04d %02d %02d, %02d:%02d:%02d **********\n\n",
    1770           HV_CONTROL_VERSION,
    1771           1900 + time_now->tm_year,
    1772           1 + time_now->tm_mon,
    1773           time_now->tm_mday,
    1774           time_now->tm_hour,
    1775           time_now->tm_min,
    1776           time_now->tm_sec);
    1777  
    1778   for (int i=0;i<status->NumHVBoards;i++) {
    1779     fprintf(fptr,"Device: %s\n\n",status->fUSBDevice[i]);
    1780    
    1781     for (int j=0;j<MAX_NUM_CHAINS;j++) {
    1782       for (int k=0;k<4;k++) {
    1783         for (int l=0;l<8;l++)
    1784           fprintf(fptr,"%5d ",status->HV[i][j][k*8+l]);
    1785         fprintf(fptr,"\n");
    1786       }
    1787       fprintf(fptr,"\n");
    1788     }
    1789   }
    1790    
    1791   fclose(fptr);
    1792 
    1793   return 1;
    1794 }
    1795 
    1796 
    1797 int ProcessIO::IsBoard(int board) {
    1798 
    1799   for (int i=0;i<MAX_NUM_HVBOARDS;i++)
    1800     if (board == status->USBDeviceNumber[i])
    1801       return 1;
    1802 
    1803   return 0;
    1804 }
    1805 
    1806 
    1807 int ProcessIO::GetBoardIdx(int board) {
    1808 
    1809   for (int i=0;i<MAX_NUM_HVBOARDS;i++)
    1810     if (board == status->USBDeviceNumber[i])
    1811       return i;
    1812 
    1813   return -1;
    1814 }
     709      Param[Count] = Command;
     710      while(!isspace(*Command) && *Command!='\0') Command++;
     711    }
     712    if(*Command != '\0') *Command++ = '\0';
     713    Count++;
     714  }
     715  return Count;
     716}
     717
     718// Check if two strings match (min 1 character must match)
     719bool Match(const char *str, const char *cmd) {
     720  return strncasecmp(str,cmd,strlen(str)==0 ? 1:strlen(str)) ? false:true;
     721}
     722
     723// Convert string to double
     724// Returns false if conversion did not stop on whitespace or EOL character
     725bool ConvertToDouble(const char *String, double *Result) {
     726
     727  char *EndPointer;
     728 
     729  *Result = strtod(String, &EndPointer);
     730  if(!isspace(*EndPointer) && *EndPointer!='\0') return false;
     731  return true;
     732}
     733
     734
     735// Convert string to int
     736// Returns false if conversion did not stop on whitespace or EOL character
     737bool ConvertToInt(const char *String, int *Result) {
     738
     739  char *EndPointer;
     740 
     741  *Result = (int) strtol(String, &EndPointer, 0);
     742  if(!isspace(*EndPointer) && *EndPointer!='\0') return false;
     743  return true;
     744}
  • hvcontrol/src/ProcessIO.h

    r35 r90  
    33#define PROCESSIO_H_SEEN
    44
    5 #include <stdio.h>
    6 #include <stdlib.h>
    7 #include <string.h>
    85#include <stdarg.h>
    9 #include <limits.h>
    10 #include <time.h>
    116#include <errno.h>
    12 #include <unistd.h>
    137#include <math.h>
    14 #include <pthread.h>
    15 #include <termios.h>
    16 #include <fcntl.h>
    17 #include <assert.h>
    18 #include <dirent.h>
    19 #include <sys/time.h> 
    20 #include <sys/types.h>
    21 #include <sys/socket.h>
    22 #include <sys/ioctl.h>
    23 #include <sys/select.h>
    248#include <signal.h>
    259
    26 #include "Types.h"
    27 #include "HVStatus.h"
    28 #include "Log.h"
    2910#include "HVConfig.h"
    3011#include "HVCalib.h"
    31 #include "Utilities.h"
    3212#include "HV.h"
     13#include "../pixelmap/PixelMap.h"
    3314
    34 #include <iostream>
    35 #include "../../fact_repos.svn/pixelmap/PixelMap.h"
     15#define MAX_NUM_TOKEN 10
    3616
     17#define MsgToConsole 1
     18#define MsgToLog 2
     19#define MsgToSocket 4
     20
     21typedef enum stateenum { active, stopped, na } state_enum;
    3722
    3823class ProcessIO {
    3924
    40  private:
    41  
    4225  time_t StartTime;
    43 
    44   char str[MAX_COM_SIZE];
    45 
    46   unsigned char wbuf[BUFFER_LENGTH];
    47   unsigned char rbuf[BUFFER_LENGTH];
    48 
    49   char bdata[16];
    50 
     26  FILE *Logfile;
    5127  PixelMap *pm;
    5228
    5329 public:
    5430 
    55   HVConfig*    config;
    56   HVCalib*     calib;
    57   Status*      status;
    58   Log*         log;
     31  HVConfig    *config;
     32  HVCalib     *calib;
     33  HVBoard* fHVBoard[MAX_NUM_HVBOARDS];
    5934
    6035  pthread_mutex_t control_mutex;
    61   pthread_cond_t  control_cond;
    6236
     37  char Prompt[MAX_COM_SIZE];
     38  const char *Param[MAX_NUM_TOKEN]; // For parser
     39  int NParam;
     40  bool CmdFromSocket;
    6341 
    64   HV *hv;
    65   HVBoard *hvboard;
     42  // Status variables 
     43  pthread_t HVMonitor;       // exit function sends signal to these threads
     44  pthread_t SocketThread;
     45
     46  bool Verbose; 
     47  int Socket;                // -1 if not connected
     48
     49  int NumHVBoards;
     50  int FirstBoard;
     51  int LastBoard;
     52  int FirstChain;
     53  int LastChain;
    6654 
    67 
    68   ProcessIO(char *config_file);
     55  float fStatusRefreshRate;
     56  state_enum   state;
     57  bool Exit;
     58   
     59  // Methods
     60  ProcessIO(char *);
    6961  ~ProcessIO();
    7062
    71   void Scan();
    72   void PrintHelp();
    73   void PrintDateAndTime();
    74   void DoPrompt(char* str);
    75   void PrintMessage(char* str);
    76   void PrintMessageToLog(char *str);
    77   void PrintMessageO(char *Format, ...);
    78   int CommandControl();
    79   int NBoards();
    80   int InitializeHV();
    81   void UpdateStatus(int i, unsigned char* rbuf);
     63  void PrintMessage(int, const char *, ...);
     64  void PrintMessage(const char *, ...);
     65  void PrintMessage(int, const char *, va_list);
     66  void CommandControl(char*);
     67  bool RampVoltage(unsigned int, int, int, int);
    8268  void StartMonitor();
    8369  void StopMonitor();
    8470  void Monitor();
    8571  void ResetActiveBoards();
    86   void ResetAllBoards();
    87   void ResetBoard(int i);
    88   int SaveHVSettings(char* filename);
    89   int IsBoard(int i);
    90   int GetBoardIdx(int board);
     72  void ResetBoard(int);
     73  int GetBoardIdx(int);
    9174
     75  void PrintBoardStatus(int);
     76
     77  int ParseInput(char*, const char *Param[]);
    9278};
    9379
     80bool Match(const char *, const char *);
     81bool ConvertToDouble(const char *, double *);
     82bool ConvertToInt(const char *, int *);
     83
    9484#endif
Note: See TracChangeset for help on using the changeset viewer.