Index: hvcontrol/hvcontrol.cpp
===================================================================
--- hvcontrol/hvcontrol.cpp	(revision 161)
+++ hvcontrol/hvcontrol.cpp	(revision 183)
@@ -14,7 +14,4 @@
 #include <pthread.h>
 #include <signal.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
 
 #include "ProcessIO.h"
@@ -23,10 +20,8 @@
 #include <readline/history.h>
 
-#define DEFAULT_CONFIG "../config/HV.conf"     // Default configuration file
 #define LOCKFILE "/tmp/CTX_HV_LOCK"
 
 // Function prototypes
 void ConsoleCommand(ProcessIO *);
-void CCCommand(ProcessIO *);
 void HVMonitor(ProcessIO *);
 void DummyHandler(int);
@@ -43,12 +38,6 @@
 
   char str[MAX_COM_SIZE];
-  pthread_t thread_ConsoleCommand,thread_HVMonitor,thread_CCCommand;
+  pthread_t thread_ConsoleCommand,thread_HVMonitor;
   int LockDescriptor;
-
-  // Interpret command line (do before lockfile creation in case of exit())
-  if((argc==3 && strcmp(argv[1],"-c")!=0) || argc==2) {
-    printf("Usage: %s [-c <ConfigFile>]    Default file is \"%s\"\n", argv[0], DEFAULT_CONFIG);
-    exit(EXIT_SUCCESS);
-  }
 
   // Assure only one instance of the HV control program runs
@@ -69,5 +58,5 @@
   
   system("clear");                   
-  printf("\n*** HV Control built %s, %s (S.Commichau, S.Stark, O.Grimm) ***\n\n",__DATE__,__TIME__);
+  printf("\n*** Bias control (%s, %s, O. Grimm, S.Commichau, S.Stark) ***\n\n",__DATE__,__TIME__);
  
   // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls
@@ -84,5 +73,5 @@
   
   // Construct main instance and create mutex for thread synchronization
-  ProcessIO pio(argc==3 ? argv[2] : DEFAULT_CONFIG);
+  ProcessIO pio;
   if (pthread_mutex_init(&pio.control_mutex, NULL) != 0) {
     perror("pthread_mutex_init failed");
@@ -105,15 +94,9 @@
     throw;
   }
-  if ((pthread_create(&thread_CCCommand, NULL, (void * (*)(void *)) CCCommand,(void *) &pio)) != 0) {
-    perror("pthread_create failed with socket thread");
-    throw;
-  }
 
   // Threads should be accessible for sending signals
   pio.HVMonitor = thread_HVMonitor;
-  pio.SocketThread = thread_CCCommand;
 
   // Wait for threads to quit
-  pthread_join(thread_CCCommand, NULL);
   pthread_join(thread_ConsoleCommand, NULL);
   pthread_join(thread_HVMonitor, NULL);
@@ -169,110 +152,8 @@
     if(strlen(Command)>0) add_history(Command);
 
-    // Log command
-    m->PrintMessage(Log, "CONSOLE> %s\n", Command);
-
-    // Process command     
-    pthread_mutex_lock(&m->control_mutex);
-    m->CommandControl(Command);
-    pthread_mutex_unlock(&m->control_mutex);
-          
+    // Process command (via DIM gives automatic serialisation)
+	DimClient::sendCommand("Bias/Command", Command);
     free(Command);
   }
-}
-
-
-/********************************************************************\
-
-  CCCommand thread
-
-  Listen to commands from socket (Central Control)
-  
-  This thread will block execution in the accept() and read() socket function
-  while waiting for a connection or data. If the exit function is invoked through
-  keyboard command, these blocking functions are interrupted by raising the signal
-  SIGUSR1. Testing on errno=EINTR indicates this termination. The dummy signal
-  handler below is needed to prevent the standard thread termination occurring
-  when this signal is received.
-  
-\********************************************************************/
-
-
-void CCCommand(ProcessIO *m) {
-
-  int ServerSocket,ConnectionSocket,ReadResult;
-  struct sockaddr_in SocketAddress, ClientAddress;
-  struct hostent *ClientName;
-  socklen_t SizeClientAddress=sizeof(ClientAddress);
-  char Command[MAX_COM_SIZE];
-
-  // Set up server socket
-  if ((ServerSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
-    m->PrintMessage(All, "Could not open server socket, no remote connection possible (%s).\n", strerror(errno));
-    return;
-  }
-
-  // Allows immediate reuse of socket after closing (circumvents TIME_WAIT)
-  int Value=1;
-  if (setsockopt(ServerSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &Value, sizeof (Value)) == -1) {
-    m->PrintMessage(All, "Warning: Could not set server socket option SO_REUSEADDR (%s)\n", strerror(errno));
-  }
-
-  SocketAddress.sin_family = PF_INET;
-  SocketAddress.sin_port = htons((unsigned short) m->fCCPort);
-  SocketAddress.sin_addr.s_addr = INADDR_ANY;
-
-  if (bind(ServerSocket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1) {
-    m->PrintMessage(All, "Could not bind port to socket (%s)\n", strerror(errno));
-    close(ServerSocket);
-    return;
-  }
-  if (listen(ServerSocket, 0) == -1) {
-    m->PrintMessage(All, "Could not set socket to listening (%s)\n", strerror(errno));
-    close(ServerSocket);
-    return;
-  }
-  
-  while (!m->Exit) { // Looping to wait for incoming connection
-
-    if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) {
-      if (errno!=EINTR) m->PrintMessage(All, "Failed to accept incoming connection (%s)\n", strerror(errno));
-      close(ServerSocket);
-      return;
-    }
-
-    ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET);
-    m->PrintMessage(All, "Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown");
-    m->Socket = ConnectionSocket;
-
-    // Looping as long as client exists and program not terminated
-    while (!m->Exit) {
-
-      // Try to read command from socket
-      memset(Command, 0, sizeof(Command));
-      ReadResult = read(ConnectionSocket, Command, MAX_COM_SIZE);
-      if (ReadResult==0) break; // Client does not exist anymore
-      if (ReadResult==-1) {
-		if (errno!=EINTR) m->PrintMessage(All, "Error read from socket (%s)\n", strerror(errno));
-		break;
-      }
-      if (Command[strlen(Command)-1]=='\n') Command[strlen(Command)-1]='\0';  // Remove trailing newline
-      
-      // Log command
-      //m->PrintMessage(Console, "SOCKET> %s\n", Command);
-      //m->PrintMessage(Log, "SOCKET> %s\n", Command);
-	    
-      // Process command
-      pthread_mutex_lock(&m->control_mutex);
-      m->CmdFromSocket = true;
-      m->CommandControl(Command);
-      m->CmdFromSocket = false;
-      pthread_mutex_unlock(&m->control_mutex);	
-    }
-
-    m->Socket = -1;
-    m->PrintMessage(All, "Disconnected from client.\n");
-    close(ConnectionSocket);
-  } 
-  close(ServerSocket); 
 }
 
Index: hvcontrol/src/HV.cc
===================================================================
--- hvcontrol/src/HV.cc	(revision 161)
+++ hvcontrol/src/HV.cc	(revision 183)
@@ -30,11 +30,8 @@
   Name = new DimService (Buffer, BoardName);
 
-  for (int i=0; i<NUM_CHAINS; i++) {
-    for (int j=0; j<NUM_CHANNELS; j++) {
-      snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/VOLT/ID%.2d/%.2d-%.3d", BoardNumber, i, j);
-      BiasVolt[i][j] = new DimService (Buffer, HVV[i][j]);
-    }
-    Overcurrent[i] = false;
-  }
+  snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/VOLT/ID%.2d", BoardNumber);
+  BiasVolt = new DimService (Buffer, "D", HVV, NUM_CHAINS*NUM_CHANNELS*sizeof(double));
+
+  for (int i=0; i<NUM_CHAINS; i++) Overcurrent[i] = false;
   ResetButton = false;
   WrapOK = true;
@@ -87,9 +84,5 @@
 
   delete Name;
-  for (int i=0; i<NUM_CHAINS; i++) {
-    for (int j=0; j<NUM_CHANNELS; j++) {
-      delete BiasVolt[i][j];
-    }
-  }
+  delete BiasVolt;
 }
 
@@ -202,10 +195,9 @@
     for (int k=0; k<NUM_CHANNELS; k++){
       HV[j][k] = 0;
-      HVV[j][k] = 0.0;
-      
-      // Update DIM services
-      BiasVolt[j][k]->updateService();
+      HVV[j][k] = 0.0;      
     }
   }
+  // Update DIM services
+  BiasVolt->updateService();
 }
 
Index: hvcontrol/src/HV.h
===================================================================
--- hvcontrol/src/HV.h	(revision 161)
+++ hvcontrol/src/HV.h	(revision 183)
@@ -55,5 +55,5 @@
 
    DimService *Name;
-   DimService *BiasVolt[NUM_CHAINS][NUM_CHANNELS];
+   DimService *BiasVolt;
 
    void ClearVoltageArrays();
Index: hvcontrol/src/ProcessIO.cc
===================================================================
--- hvcontrol/src/ProcessIO.cc	(revision 161)
+++ hvcontrol/src/ProcessIO.cc	(revision 183)
@@ -14,6 +14,5 @@
 static char* state_str[]    = {"active", "stopped", "n.a."};
 
-
-ProcessIO::ProcessIO(const char *ConfigFile): 
+ProcessIO::ProcessIO(): 
     	    DimCommand((char *) SERVER_NAME"/Command", (char *) "C"),
     	    EvidenceServer(SERVER_NAME) {
@@ -24,10 +23,9 @@
   // Create DIM text output service
   Textout = new DimService (SERVER_NAME"/Textout", (char *) "");
+  UpdateDelay = 0.0;
 
   // Initialize status variables
   state     = active;
   Exit      = false;
-  CmdFromSocket = false;
-  Socket    = -1;
   
   NumHVBoards = 0;
@@ -38,14 +36,13 @@
 
   // Get configuration data
-  char *Boards = GetConfig(SERVER_NAME " Boards");
-  fPixMapTable = GetConfig(SERVER_NAME " PixMapTable");
-  fTimeOut = atof(GetConfig(SERVER_NAME " TimeOut"));
-  fStatusRefreshRate = atof(GetConfig(SERVER_NAME " StatusRefreshRate"));
-  fCCPort = atoi(GetConfig(SERVER_NAME " CCPort"));
-  DACMin = atoi(GetConfig(SERVER_NAME " DACMin"));
-  DACMax = atoi(GetConfig(SERVER_NAME " DACMax"));
-  fHVCalibOffset = atof(GetConfig(SERVER_NAME " HVCalibOffset"));
-  fHVCalibSlope = atof(GetConfig(SERVER_NAME " HVCalibSlope"));
-  fHVMaxDiff = atoi(GetConfig(SERVER_NAME " HVMaxDiff"));
+  char *Boards = GetConfig("Boards");
+  fPixMapTable = GetConfig("PixMapTable");
+  fTimeOut = atof(GetConfig("TimeOut"));
+  fStatusRefreshRate = atof(GetConfig("StatusRefreshRate"));
+  DACMin = atoi(GetConfig("DACMin"));
+  DACMax = atoi(GetConfig("DACMax"));
+  fHVCalibOffset = atof(GetConfig("HVCalibOffset"));
+  fHVCalibSlope = atof(GetConfig("HVCalibSlope"));
+  fHVMaxDiff = atoi(GetConfig("HVMaxDiff"));
 
   if (fStatusRefreshRate < MIN_RATE || fStatusRefreshRate > MAX_RATE)  fStatusRefreshRate = 1;
@@ -164,5 +161,4 @@
     PrintMessage( " TimeOut:           %.2f s\n"
     	    	  " StatusRefreshRate: %.2f Hz\n"
-    	    	  " CCPort:            %d\n"
     	    	  " DACMin value:      %d\n"
     	    	  " DACMax value:      %d\n"
@@ -170,5 +166,5 @@
     	    	  " HVCalibSlope :     %f\n"
     	    	  " HVMaxDiff :        %u\n", fTimeOut,
-		  fStatusRefreshRate, fCCPort, DACMin,
+		  fStatusRefreshRate, DACMin,
 		  DACMax, fHVCalibOffset, fHVCalibSlope,
 		  fHVMaxDiff);
@@ -182,6 +178,5 @@
     PrintMessage(" board <i>|<i> <j>|<all>           Address board i, boards i-j or all boards or list boards\n"
     	" chain <i>|<i> <j>|<all>           Address chain i, chains i-j or all chains\n"
-    	" hv <PXL id>|<ch>|<all> <v>        Set bias of pixel ID, ch. or all ch. of active chain(s)/board(s)\n"
-    	" hvdiff <PXL id>|<ch>|<all> <diff> Change bias by <diff>\n"
+    	" hv <PXL id>|<ch>|<all> <v>        Set/change bias of pixel, ch. or all ch. of active chain(s)/board(s)\n"
 		" status [dac]                      Show status information (DAC values if requested)\n"
 		" config                            Print configuration\n"
@@ -204,5 +199,5 @@
   // Set new bias voltage (if no boards available, simply returns OK)
   // First reponse to socket should be 'OK' if no error occurred.
-  if (Match(Param[0], "hv") || Match(Param[0], "hvdiff")) {
+  if (Match(Param[0], "hv")) {
 
     int hvoltage, DACValue, Errors=0, Board=-1, Chain=-1, Channel=-1;
@@ -212,5 +207,5 @@
     // Need two or parameters
     if (NParam<3 || NParam>4) {
-      PrintMessage("Usage: hv/hvdiff <channel>|<all> <voltage> [dac]\n");
+      PrintMessage("Usage: hv <channel>|<all> <voltage> [dac]\n");
       return;
     }
@@ -250,15 +245,15 @@
 	  if (k!=Channel && Channel!=-1) continue;
 
-	  // hvdiff is ignored if DAC value is zero
-	  if ((strlen(Param[0])>2 || isdigit(*Param[2])==0) && (fHVBoard[i]->HV[j][k] == 0)) continue;
+	  // Voltage change ignored if DAC value is zero
+	  if (isdigit(*Param[2])==0 && fHVBoard[i]->HV[j][k] == 0) continue;
 
 	  // Determine new DAC values
 	  if (!SetDac){
-		if (strlen(Param[0])>2 || isdigit(*Param[2])==0) fHVBoard[i]->HVV[j][k] += hvoltageV; // hvdiff
+		if (isdigit(*Param[2])==0) fHVBoard[i]->HVV[j][k] += hvoltageV; // voltage change
 	    else fHVBoard[i]->HVV[j][k] = hvoltageV;
 	    DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k);
 	  }
 	  else {
-	    if(strlen(Param[0])>2 || isdigit(*Param[2])==0) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // hvdiff
+	    if (isdigit(*Param[2])==0) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // voltage change
 	    else DACValue = hvoltage;
 	  }
@@ -269,12 +264,11 @@
 
       // Update DIM services
-      fHVBoard[i]->BiasVolt[j][k]->updateService();
-
+      //fHVBoard[i]->BiasVolt[j][k]->updateService();
+	  UpdateDelay = 1.0;
 	} // Channels	
     } // Chains
     } // Boards
 
-    if (Errors > 0) PrintMessage("ERROR - Errors on %d channel(s) occurred\n", Errors);
-    else PrintMessage("OK - no errors\n");
+    if (Errors > 0) PrintMessage("Errors on %d channel(s) occurred\n", Errors);
     
     return;
@@ -318,6 +312,6 @@
 
 	    // Update DIM services
-    	    fHVBoard[Board]->BiasVolt[Chain][Channel]->updateService();
-
+    	    //fHVBoard[Board]->BiasVolt[Chain][Channel]->updateService();
+		UpdateDelay = 1.0;
 	    if(++Channel == NUM_CHANNELS) {
 	      Chain++;
@@ -440,5 +434,4 @@
     PrintMessage("\n Status monitor: %s\n", state_str[state]);
     PrintMessage(" Status refresh rate [Hz]: %.2f\n", fStatusRefreshRate);
-    PrintMessage(" Socket state: %s\n", Socket==-1 ? "disconnected":"connected");
     PrintMessage(" Total number of boards: %d\n", NumHVBoards);
     PrintMessage(" Active boards: %d\n\n", LastBoard - FirstBoard + 1);
@@ -519,13 +512,6 @@
   else if(Match(Param[0], "exit")) {
 
-    if (CmdFromSocket) {
-      PrintMessage("Exit command not allowed over socket.\n");
-      return;
-    }  	
-
     Exit = true;
-    pthread_kill(HVMonitor, SIGUSR1);
-    pthread_kill(SocketThread, SIGUSR1);
- 
+    pthread_kill(HVMonitor, SIGUSR1); 
     return;
   }
@@ -549,6 +535,5 @@
   va_list ArgumentPointer;
   va_start(ArgumentPointer, Format);
-  if (CmdFromSocket) DoPrintMessage(Format, ArgumentPointer, Client);
-  else DoPrintMessage(Format, ArgumentPointer, Console);
+  DoPrintMessage(Format, ArgumentPointer, Console);
   va_end(ArgumentPointer);
 }
@@ -575,17 +560,12 @@
   Textout->updateService(Textbuffer); 
 
-  // Print to socket
-  if((Target & Client) && Socket!=-1) {
-    write(Socket, Textbuffer, strlen(Textbuffer));
-  }
-
   // Send to log
   if(Target & Log) {
     char *Buf;
     if (asprintf(&Buf, "%s %s", SERVER_NAME, Textbuffer) != -1) { 
-      DimClient::sendCommand("DColl/Log", Buf);
+      DimClient::sendCommandNB("DColl/Log", Buf);
       free(Buf);
     }
-    else DimClient::sendCommand("DColl/Log", SERVER_NAME" asprintf() failed"); 
+    else DimClient::sendCommandNB("DColl/Log", SERVER_NAME" asprintf() failed"); 
   }
 }
@@ -648,5 +628,11 @@
       }
     }
-    
+  }
+
+  if (UpdateDelay >= 0) {
+	UpdateDelay -= 1.0/(NumHVBoards*fStatusRefreshRate);
+	if (UpdateDelay <= 0) for (int i=0; i<NumHVBoards; i++) {
+	  fHVBoard[i]->BiasVolt->updateService();
+	}
   }
 }
@@ -700,12 +686,8 @@
 
 //
-// Command handling (the only command is 'BIAS/Command')
+// Command handling (the only command is 'Bias/Command')
 //
 void ProcessIO::commandHandler() {
 
-    // Log command
-    PrintMessage(Log, "DIM> %s\n", getString());
-
-    // Process command     
     pthread_mutex_lock(&control_mutex);
     CommandControl(getString());
Index: hvcontrol/src/ProcessIO.h
===================================================================
--- hvcontrol/src/ProcessIO.h	(revision 161)
+++ hvcontrol/src/ProcessIO.h	(revision 183)
@@ -28,5 +28,5 @@
 #define MAX_NUM_TOKEN 10
 
-enum MsgTarget {Console=1, Log=2, Client=4, All=7};
+enum MsgTarget {Console=1, Log=2, All=7};
 typedef enum stateenum {active, stopped, na} state_enum;
 
@@ -36,10 +36,10 @@
   PixelMap *pm;
   DimService *Textout;
-  
+  float UpdateDelay;
+
   void commandHandler();
 
  public:
-  
-  //HVConfig    *config;
+
   HVCalib     *calib;
   HVBoard **fHVBoard;
@@ -50,5 +50,4 @@
   const char *Param[MAX_NUM_TOKEN]; // For parser
   int NParam;
-  bool CmdFromSocket;
 
   // Configuration data
@@ -56,5 +55,4 @@
   float fTimeOut;
   float fStatusRefreshRate;
-  int fCCPort;
   int DACMin;
   int DACMax;
@@ -65,8 +63,5 @@
   // Status variables  
   pthread_t HVMonitor;       // exit function sends signal to these threads
-  pthread_t SocketThread;
   
-  int Socket;                // -1 if not connected
-
   int NumHVBoards;
   int FirstBoard;
@@ -79,5 +74,5 @@
     
   // Methods
-  ProcessIO(const char *);
+  ProcessIO();
   ~ProcessIO();
 
