Index: /hvcontrol/History.txt
===================================================================
--- /hvcontrol/History.txt	(revision 160)
+++ /hvcontrol/History.txt	(revision 161)
@@ -26,4 +26,10 @@
 24/9/2009   Program is terminated if too many errors are encountered by the
     	    monitor thread
-8/12/2009   Implemented DIM servers (currently only needs DIM_DNS_NODE
-    	    environment variable)
+8/12/2009   Implemented DIM servers
+15/12/2009  Removed local log file and implemented logging via DColl
+17/12/2009	Implemented DIM command handling and 'Textout' DIM service
+8/1/2010	Removed locale slow data writing, now handled by Evidence
+13/1/2010	Only important messages are written to log file
+20/1/2010	Removed local configuration, now dependent on Evidence configuration
+			server
+29/1/2010	DAC value 0 is now equivilant to calibrated voltage value 0
Index: /hvcontrol/Makefile
===================================================================
--- /hvcontrol/Makefile	(revision 160)
+++ /hvcontrol/Makefile	(revision 161)
@@ -3,12 +3,12 @@
 #
 
-SOURCES = hvcontrol.cpp src/HV.cc src/HVConfig.cc src/HVCalib.cc src/ProcessIO.cc ../pixelmap/Pixel.cc ../pixelmap/PixelMap.cc ../drsdaq/SlowData.cc ../Evidence/Evidence.cc 
+SOURCES = hvcontrol.cpp src/HV.cc src/HVCalib.cc src/ProcessIO.cc ../pixelmap/Pixel.cc ../pixelmap/PixelMap.cc ../Evidence/Evidence.cc 
 OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) 
-INCDIRS   = -I. -I./src -I../Evidence/DIM/
+INCDIRS   = -I. -I../Evidence -I./src -I$(DIMDIR)/dim
 
-CPPFLAGS = -O3 -Wall -DOS_LINUX $(INCDIRS)
-LDLIBS = -lstdc++ -lpthread -lfl -lreadline -ltermcap
+CPPFLAGS = -O3 -Wall $(INCDIRS)
+LDLIBS = -lstdc++ -lpthread -lfl -lreadline -ltermcap $(DIMDIR)/linux/libdim.a
 
-hvcontrol: $(OBJECTS) ../Evidence/DIM/libdim.a
+hvcontrol: $(OBJECTS)
 
 clean:
Index: /hvcontrol/hvcontrol.cpp
===================================================================
--- /hvcontrol/hvcontrol.cpp	(revision 160)
+++ /hvcontrol/hvcontrol.cpp	(revision 161)
@@ -93,5 +93,5 @@
   signal(SIGQUIT, &CrashHandler);  // CTRL-Backspace
   signal(SIGINT, &CrashHandler);   // CTRL-C
-  signal(SIGHUP, &CrashHandler);  // CTRL-Backspace
+  signal(SIGHUP, &CrashHandler);   // Terminal closed
   signal(SIGTERM, &CrashHandler);
 
@@ -170,5 +170,5 @@
 
     // Log command
-    m->PrintMessage(MsgToLog, "CONSOLE> %s\n", Command);
+    m->PrintMessage(Log, "CONSOLE> %s\n", Command);
 
     // Process command     
@@ -208,5 +208,5 @@
   // Set up server socket
   if ((ServerSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
-    m->PrintMessage("Could not open server socket, no remote connection possible (%s).\n", strerror(errno));
+    m->PrintMessage(All, "Could not open server socket, no remote connection possible (%s).\n", strerror(errno));
     return;
   }
@@ -215,18 +215,18 @@
   int Value=1;
   if (setsockopt(ServerSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &Value, sizeof (Value)) == -1) {
-    m->PrintMessage("Warning: Could not set server socket option SO_REUSEADDR (%s)\n", strerror(errno));
+    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->config->fCCPort);
+  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("Could not bind port to socket (%s)\n", strerror(errno));
+    m->PrintMessage(All, "Could not bind port to socket (%s)\n", strerror(errno));
     close(ServerSocket);
     return;
   }
   if (listen(ServerSocket, 0) == -1) {
-    m->PrintMessage("Could not set socket to listening (%s)\n", strerror(errno));
+    m->PrintMessage(All, "Could not set socket to listening (%s)\n", strerror(errno));
     close(ServerSocket);
     return;
@@ -236,5 +236,5 @@
 
     if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) {
-      if (errno!=EINTR) m->PrintMessage("Failed to accept incoming connection (%s)\n", strerror(errno));
+      if (errno!=EINTR) m->PrintMessage(All, "Failed to accept incoming connection (%s)\n", strerror(errno));
       close(ServerSocket);
       return;
@@ -242,5 +242,5 @@
 
     ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET);
-    m->PrintMessage("Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown");
+    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;
 
@@ -253,11 +253,12 @@
       if (ReadResult==0) break; // Client does not exist anymore
       if (ReadResult==-1) {
-	if (errno!=EINTR) m->PrintMessage("Error read from socket (%s)\n", strerror(errno));
-	break;
+		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(MsgToConsole|MsgToLog, "SOCKET> %s\n", Command);
+      //m->PrintMessage(Console, "SOCKET> %s\n", Command);
+      //m->PrintMessage(Log, "SOCKET> %s\n", Command);
 	    
       // Process command
@@ -270,5 +271,5 @@
 
     m->Socket = -1;
-    m->PrintMessage("Disconnected from client.\n");
+    m->PrintMessage(All, "Disconnected from client.\n");
     close(ConnectionSocket);
   } 
Index: /hvcontrol/src/HV.cc
===================================================================
--- /hvcontrol/src/HV.cc	(revision 160)
+++ /hvcontrol/src/HV.cc	(revision 161)
@@ -22,5 +22,5 @@
   m = PIO;
 
-  SetTimeOut(m->config->fTimeOut);
+  SetTimeOut(m->fTimeOut);
   BoardNumber = DeviceNumber;
   BoardName = DeviceName;
@@ -34,6 +34,4 @@
       snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/VOLT/ID%.2d/%.2d-%.3d", BoardNumber, i, j);
       BiasVolt[i][j] = new DimService (Buffer, HVV[i][j]);
-      snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/DAC/ID%.2d/%.2d-%.3d", BoardNumber, i, j);
-      BiasDAC[i][j] = new DimService (Buffer, HV[i][j]);
     }
     Overcurrent[i] = false;
@@ -43,5 +41,5 @@
   LastWrapCount = -1;
   ErrorCount = 0;
-  
+
   ClearVoltageArrays();
 
@@ -49,5 +47,5 @@
   snprintf(Buffer, BUFFER_LENGTH, "/dev/%s",DeviceName);
   if ((fDescriptor = open(Buffer, O_RDWR|O_NOCTTY|O_NDELAY)) == -1) {
-    if(errno != 2) m->PrintMessage("Error: Could not open device %d/%s (%s)\n", DeviceNumber,DeviceName, strerror(errno));
+    if(errno != 2) m->PrintMessage(All, "Error: Could not open device %d/%s (%s)\n", DeviceNumber,DeviceName, strerror(errno));
     return;
   }
@@ -55,12 +53,12 @@
   // Get current serial port settings
   if (tcgetattr(fDescriptor, &tio) == -1) {
-    m->PrintMessage("Error: tcgetattr() failed (%d/%s)\n", errno, strerror(errno));
+    m->PrintMessage(All, "Error: tcgetattr() failed (%d/%s)\n", errno, strerror(errno));
     return;   
   }
 
   // Set baudrate and raw mode
-  if (cfsetspeed(&tio, BAUDRATE) == -1) m->PrintMessage("Error: Could not set baud rate (%s)\n", strerror(errno));
+  if (cfsetspeed(&tio, BAUDRATE) == -1) m->PrintMessage(All, "Error: Could not set baud rate (%s)\n", strerror(errno));
   cfmakeraw(&tio);
-  if (tcsetattr(fDescriptor, TCSANOW, &tio ) == -1) m->PrintMessage("Error: tcsetattr() failed (%s)\n", strerror(errno));
+  if (tcsetattr(fDescriptor, TCSANOW, &tio ) == -1) m->PrintMessage(All, "Error: tcsetattr() failed (%s)\n", strerror(errno));
 
   //  Synchronize HV board (if fails, closes device and sets fDescriptor to -2) 
@@ -92,5 +90,4 @@
     for (int j=0; j<NUM_CHANNELS; j++) {
       delete BiasVolt[i][j];
-      delete BiasDAC[i][j];
     }
   }
@@ -109,12 +106,8 @@
   // === Write data ===
   if ((ret=write(fDescriptor, wbuf, Bytes)) < Bytes) {
-    if (ret == -1) m->PrintMessage("Could not write data to HV board (%s)\n", strerror(errno));
-    else m->PrintMessage("Could write only %d of %d bytes to HV board\n", ret, Bytes);
+    if (ret == -1) m->PrintMessage(All, "Could not write data to HV board (%s)\n", strerror(errno));
+    else m->PrintMessage(All, "Could write only %d of %d bytes to HV board\n", ret, Bytes);
     ErrorCount++;
     return 0;
-  }
-  if (m->Verbose) {
-    m->PrintMessage("%d bytes written:\n", Bytes);
-    for (int i=0; i<Bytes; i++) m->PrintMessage(" Byte %d: %#.2x\n",i,wbuf[i]);
   }
 
@@ -123,15 +116,13 @@
   struct timeval WaitTime = {(long) fTimeOut, (long) ((fTimeOut-(long) fTimeOut)*1e6)};
   if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
-    m->PrintMessage("Error with select() (%s)\n", strerror(errno));
+    m->PrintMessage(All, "Error with select() (%s)\n", strerror(errno));
     return 0;
   }
   // Time-out expired?
-  if (!FD_ISSET(fDescriptor, &SelectDescriptor)) {
-    if (m->Verbose) m->PrintMessage("Time-out of %.2f seconds expired while reading\n", fTimeOut);
-    return -1;
-  }
+  if (!FD_ISSET(fDescriptor, &SelectDescriptor)) return -1;
+
   // Read error?    
   if ((ret = read(fDescriptor, &rbuf, 1)) == -1) {
-    m->PrintMessage("Read error (%s)\n", strerror(errno));
+    m->PrintMessage(All, "Read error (%s)\n", strerror(errno));
     ErrorCount++;
     return 0;
@@ -147,6 +138,4 @@
   ResetButton = (bool) (rbuf & 0X80);
 
-  if (m->Verbose && ret==1) m->PrintMessage(" 1 byte read: %#.2x\n", rbuf);  
-  
   return 1;
 }
@@ -217,5 +206,4 @@
       // Update DIM services
       BiasVolt[j][k]->updateService();
-      BiasDAC[j][k]->updateService();
     }
   }
Index: /hvcontrol/src/HV.h
===================================================================
--- /hvcontrol/src/HV.h	(revision 160)
+++ /hvcontrol/src/HV.h	(revision 161)
@@ -9,6 +9,7 @@
 #include <sys/ioctl.h>
 
-#include "HVConfig.h"
 #include "dis.hxx"
+#define NUM_CHAINS 4
+#define NUM_CHANNELS 32
 
 #define BAUDRATE B115200
@@ -55,5 +56,4 @@
    DimService *Name;
    DimService *BiasVolt[NUM_CHAINS][NUM_CHANNELS];
-   DimService *BiasDAC[NUM_CHAINS][NUM_CHANNELS];
 
    void ClearVoltageArrays();
Index: /hvcontrol/src/HVCalib.cc
===================================================================
--- /hvcontrol/src/HVCalib.cc	(revision 160)
+++ /hvcontrol/src/HVCalib.cc	(revision 161)
@@ -19,8 +19,10 @@
 #include "HVCalib.h"
 
+#include "ProcessIO.h" // Must be not in HVCalib.h to avoid problem with declaring class ProcessIO
+
 using namespace std;
 
 
-HVCalib::HVCalib(HVConfig* hvConfig) {
+HVCalib::HVCalib(class ProcessIO *hvConfig) {
 
   char calibfile[80], dLine[6000];
@@ -31,5 +33,5 @@
 
   Config = hvConfig;
-  
+
   iDACMin = Config->DACMin;
   fHVCalibSlope = Config->fHVCalibSlope;
@@ -54,5 +56,5 @@
   for(int i=0; i<Config->NumHVBoards; i++){
     for(int j=0; j<NUM_CHAINS; j++){
-      sprintf(calibfile,"Calib/%s_%c%d.txt",hvConfig->fUSBDevice[i],65+j,1); 
+      sprintf(calibfile,"Calib/%s_%c%d.txt",hvConfig->fHVBoard[i]->BoardName,65+j,1); 
       ifstream fin(calibfile);
 
@@ -143,4 +145,7 @@
 
 double HVCalib::DACToHV(int dac, int board, int chain, int channel) {
+  
+  if (dac == 0) return 0;
+  
   if (dac < iDACMin){
     return HVArray[board][chain][channel][0] + (dac - iDACMin)*fHVCalibSlope;
@@ -153,4 +158,6 @@
 
 int HVCalib::HVToDAC(double hv, int board, int chain, int channel) {
+
+  if (hv == 0) return 0;
   if (hv < HVArray[board][chain][channel][0]){
         return iDACMin + (int)((hv - HVArray[board][chain][channel][0])/fHVCalibSlope);
Index: /hvcontrol/src/HVCalib.h
===================================================================
--- /hvcontrol/src/HVCalib.h	(revision 160)
+++ /hvcontrol/src/HVCalib.h	(revision 161)
@@ -4,6 +4,6 @@
 #include <string.h>
 
-#include "HVConfig.h"
-
+//#include "HVConfig.h"
+class ProcessIO;
 
 class HVCalib {
@@ -19,9 +19,9 @@
   double fHVCalibSlope;
 
-  HVConfig *Config;
+  class ProcessIO *Config;
   
  public:
 
-  HVCalib(HVConfig *);
+  HVCalib(class ProcessIO *);
   ~HVCalib();
 
Index: control/src/HVConfig.cc
===================================================================
--- /hvcontrol/src/HVConfig.cc	(revision 160)
+++ 	(revision )
@@ -1,104 +1,0 @@
-
-/********************************************************************\
-
-  Name:         HVConfig.cc
-
-  Created by:   Sebastian Commichau, November 2008
-                commichau@phys.ethz.ch
-
-  Contents:     Class reading the HV utility configuration file
-
-\********************************************************************/
-
-#include "HVConfig.h"
-
-
-HVConfig::HVConfig(const char *configfile) {
-
-  // Read configuration file
-  FILE *f;
-
-  if ((f = fopen(configfile,"r")) == NULL) {
-    printf("Could not open configuration file: %s\n", configfile);
-    throw;
-  }
-  printf("Opening configuration file: %s\n", configfile);
- 
-  // Determine number of entries in 'Boards' card and allocate memeory
-  NumHVBoards = (int) ReadCard("Boards", NULL, 'n', f);
-  fUSBDevice = new char* [NumHVBoards];
-  for (int i=0; i<NumHVBoards; i++) fUSBDevice[i] = new char [BUFFER_LENGTH];
-  ReadCard("Boards", fUSBDevice, 'S', f, NumHVBoards);
-
-  ReadCard("LogFile",       fLogFile,    's',f);
-  ReadCard("PixMapTable",   fPixMapTable,'s',f);
-  ReadCard("SlowDirectory", fSlowDir,	 's',f);
-  ReadCard("TimeOut",           &fTimeOut,           'f', f);
-  ReadCard("StatusRefreshRate", &fStatusRefreshRate, 'f', f);
-  ReadCard("CCPort",            &fCCPort,            'I', f);
-  ReadCard("DACMin",            &DACMin,             'I', f);
-  ReadCard("DACMax",            &DACMax,             'I', f);
-  ReadCard("HVCalibOffset",     &fHVCalibOffset,     'f', f);
-  ReadCard("HVCalibSlope",      &fHVCalibSlope,      'f', f);
-  ReadCard("HVMaxDiff",         &fHVMaxDiff,         'U', f);
-
-  fclose(f);
-}
-
-
-HVConfig::~HVConfig() {
-
-  for (int i=0; i<NumHVBoards; i++) delete[] fUSBDevice[i];
-  delete[] fUSBDevice;
-}
-
-
-// ReadCard function (original version by F. Goebel)
-// Data is read into an array if MaxNum is larger than 1
-// If Type is 'n', the number of elements for the card is counted.
-// Type 'S' is for reading an array of strings
-unsigned int ReadCard(const char *card_flag, void *store, char Type, FILE *File, unsigned int MaxNum) {
-  
-  char *card_name, *card_val, Buffer[MAX_COM_SIZE];
-  unsigned int Count=0;
-  
-  rewind(File);
-
-  while (fgets(Buffer, sizeof(Buffer), File) != NULL) {    // Read line by line
-    card_name = strtok(Buffer," \t\n");
-    
-     // Ignore empty lines, comments, and skip if card name does not match
-    if (card_name==NULL || card_name[0]=='#' || strcmp(card_name, card_flag)!=0) continue;
-
-    // Read numbers of given type (if MaxNum>1 read array)
-    while ((card_val=strtok(NULL," \t\n"))!=NULL && card_val[0]!='#' && Count++<MaxNum) {
-      switch (Type) {
-	case 'I': *(((int *&) store)++) = (int) strtol(card_val, NULL, 10);
-	      	  break;
-	case 'i': *(((short *&) store)++) = (short) strtol(card_val, NULL, 10);
-	      	  break;
-	case 'U': *(((unsigned int *&) store)++) = (unsigned int) strtoul(card_val, NULL, 10);
-	      	  break;
-	case 'u': *(((unsigned short *&) store)++) = (unsigned short) strtoul(card_val, NULL, 10);
-	      	  break;
-	case 'f': *(((float *&) store)++) = atof(card_val);
-	      	  break;
-	case 'd': *(((double *&) store)++) = atof(card_val);
-	      	  break;
-	case 's': sprintf((char *) store, "%s", card_val);
-	      	  break;
-	case 'S': sprintf(*(((char **&) store)++), "%s", card_val);
-	      	  break;
-	case 'c': *(((char *&) store)++) = card_val[0];
-	      	  break;
-  	case 'n': MaxNum = UINT_MAX;
-	      	  break;
-	default:  fprintf(stderr,"Warning: Unknown type '%c' for reading of configuration file\n", Type);
-	      	  return 0;
-      }
-    }
-    return Count;  // Finished reading data for card name  
-  }
-  return 0;
-}
-
Index: control/src/HVConfig.h
===================================================================
--- /hvcontrol/src/HVConfig.h	(revision 160)
+++ 	(revision )
@@ -1,52 +1,0 @@
-
-#ifndef HVCONFIG_H_SEEN
-#define HVCONFIG_H_SEEN
-
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-
-#define MAX_COM_SIZE 5000
-#define NUM_CHAINS 4
-#define NUM_CHANNELS 32
-#define BUFFER_LENGTH 256
-
-#define MIN_TIMEOUT 0.01
-#define MAX_TIMEOUT 5.0
-
-#define MIN_RATE 0.01
-#define MAX_RATE 50.0
-
-
-class HVConfig {
-
- public:
-
-  HVConfig(const char *);
-  ~HVConfig();
-
-  int NumHVBoards;
-  char **fUSBDevice;
-//  char (*fUSBDevice)[BUFFER_LENGTH];
-
-  char   fLogFile[BUFFER_LENGTH];
-  char   fSlowDir[BUFFER_LENGTH];
-
-  char   fPixMapTable[BUFFER_LENGTH];
-  int fCCPort;
- 
-  float  fTimeOut;
-  float  fStatusRefreshRate;
-
-  int DACMin;
-  int DACMax;
-  float  fHVCalibOffset;
-  float  fHVCalibSlope;
-  unsigned int  fHVMaxDiff;
-};
-
-unsigned int ReadCard(const char *, void *, char, FILE *, unsigned int=1);
-
-#endif
Index: /hvcontrol/src/ProcessIO.cc
===================================================================
--- /hvcontrol/src/ProcessIO.cc	(revision 160)
+++ /hvcontrol/src/ProcessIO.cc	(revision 161)
@@ -15,18 +15,17 @@
 
 
-ProcessIO::ProcessIO(const char *ConfigFile): EvidenceServer(SERVER_NAME) {
+ProcessIO::ProcessIO(const char *ConfigFile): 
+    	    DimCommand((char *) SERVER_NAME"/Command", (char *) "C"),
+    	    EvidenceServer(SERVER_NAME) {
 
   // Get program start time
   time (&StartTime);
 
-  // Create instances
-  config = new HVConfig(ConfigFile);
-  calib  = new HVCalib(config);
-  pm 	 = new PixelMap(config->fPixMapTable);
+  // Create DIM text output service
+  Textout = new DimService (SERVER_NAME"/Textout", (char *) "");
 
   // Initialize status variables
   state     = active;
   Exit      = false;
-  Verbose   = false;
   CmdFromSocket = false;
   Socket    = -1;
@@ -37,35 +36,39 @@
   FirstChain  = 0;
   LastChain   = NUM_CHAINS-1;
-  
-  if (config->fStatusRefreshRate >= MIN_RATE && config->fStatusRefreshRate <= MAX_RATE) 
-    fStatusRefreshRate = config->fStatusRefreshRate;
-  else fStatusRefreshRate = 1.;
-    
+
+  // 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"));
+
+  if (fStatusRefreshRate < MIN_RATE || fStatusRefreshRate > MAX_RATE)  fStatusRefreshRate = 1;
+
   // Open HV devices
-  fHVBoard = new HVBoard* [config->NumHVBoards]; 
-  for (int i=0; i<config->NumHVBoards; i++) {
-    fHVBoard[NumHVBoards] = new HVBoard(i, config->fUSBDevice[i], this);
+  fHVBoard = new HVBoard* [strlen(Boards)]; 
+  char *Token = strtok(Boards, " \t");
+  while (Token != NULL) {
+    fHVBoard[NumHVBoards] = new HVBoard(NumHVBoards, Token, this);
     if(fHVBoard[NumHVBoards]->fDescriptor >= 0) {
-       printf("Synchronized and reset HV board %d (%s)\n",i,config->fUSBDevice[i]);
+       PrintMessage("Synchronized and reset board %d (%s)\n",NumHVBoards,fHVBoard[NumHVBoards]->BoardName);
        NumHVBoards++;
     }
     else {
-      printf("Failed to synchronize to HV board %d (%s)\n",i,config->fUSBDevice[i]);
+      PrintMessage(All, "Failed to synchronize board %d (%s)\n",NumHVBoards,fHVBoard[NumHVBoards]->BoardName);
       delete fHVBoard[NumHVBoards];
     }
-  } 
+	Token = strtok(NULL, " \t");
+  }
   LastBoard = NumHVBoards-1;
-
-  // Open log file
-  if ((Logfile = fopen(config->fLogFile, "a")) == NULL) printf("Warning: Could not open log file '%s'\n", config->fLogFile);
-  PrintMessage(MsgToLog,"********** Logging started **********\n");
-
-  // Create instance of slow data class
-  SlowDataClass = new SlowData("HV", config->fSlowDir);
-  if (SlowDataClass->ErrorCode != 0) {
-    PrintMessage("Warning: Could not open slowdata file (%s)\n", strerror(SlowDataClass->ErrorCode));
-  }
-  SlowDataClass->NewEntry("Value-Info", "Issued if new HV value set successfull: Board-Num HV-Board-Name Chain Channel DAC-Target Converted-Value");
-  SlowDataClass->NewEntry("Error-Info", "Issued if error occurs when trying to set new HV value: Board-Num HV-Board-Name Chain Channel Attempted-DAC-Target Converted-Value");
+  
+  // Create instances
+  calib  = new HVCalib(this);
+  pm 	 = new PixelMap(fPixMapTable);  
 }
 
@@ -73,14 +76,9 @@
 ProcessIO::~ProcessIO() {
   
-  delete SlowDataClass;     
-
   for (int i=0; i<NumHVBoards; i++) delete fHVBoard[i];
   delete[] fHVBoard;
     
-  delete pm;   delete calib;    delete config;    
-  
-  if(Logfile != NULL) {
-    if(fclose(Logfile) != 0) perror("Error closing logfile");
-  }
+  delete pm;	    delete calib;
+  delete Textout;  
 }
 
@@ -97,7 +95,7 @@
 
   for(int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = "";  // All pointers point initially to empty string
-    NParam = ParseInput(Command, Param);
-
-  // Adress HV board
+  NParam = ParseInput(Command, Param);
+
+  // Adress board
   if (Match(Param[0], "board")) {
     
@@ -158,10 +156,9 @@
   // Print HV utility configuration
   else if (Match(Param[0], "config")) {
-    PrintMessage( " Log file:          %s\n"
-    	    	  " Pixel map table:   %s\n"
-    	    	  " %d USB devices:\n", config->fLogFile, config->fPixMapTable,
-		  config->NumHVBoards);  
-    for (int i=0; i<config->NumHVBoards; i++) { 
-      PrintMessage(" Board %d: %s\n", i, config->fUSBDevice[i]);
+    PrintMessage( " Pixel map table:   %s\n"
+    	    	  " %d USB devices:\n", fPixMapTable,
+		  NumHVBoards);  
+    for (int i=0; i<NumHVBoards; i++) { 
+      PrintMessage(" Board %d: %s\n", i, fHVBoard[i]->BoardName);
     }
     PrintMessage( " TimeOut:           %.2f s\n"
@@ -172,8 +169,8 @@
     	    	  " HVCalibOffset :    %f\n"
     	    	  " HVCalibSlope :     %f\n"
-    	    	  " HVMaxDiff :        %u\n", config->fTimeOut,
-		  config->fStatusRefreshRate, config->fCCPort, config->DACMin,
-		  config->DACMax, config->fHVCalibOffset, config->fHVCalibSlope,
-		  config->fHVMaxDiff);
+    	    	  " HVMaxDiff :        %u\n", fTimeOut,
+		  fStatusRefreshRate, fCCPort, DACMin,
+		  DACMax, fHVCalibOffset, fHVCalibSlope,
+		  fHVMaxDiff);
 
     return;
@@ -183,22 +180,21 @@
   // Print help
   if (Match(Param[0], "help")) {
-    puts(" board <i>|<i> <j>|<all>           Address board i, boards i-j or all boards or list boards");
-    puts(" chain <i>|<i> <j>|<all>           Address chain i, chains i-j or all chains");
-    puts(" hv <PXL id>|<ch>|<all> <v>        Set HV of pixel ID, ch. or all ch. of active chain(s)/board(s)");
-    puts(" hvdiff <PXL id>|<ch>|<all> <diff> Change HV by <diff>");
-    puts(" status [dac]                      Show status information (DAC values if requested)");
-    puts(" config                            Print configuration");
-    puts(" load <file>                       Load HV settings from <file>");
-    puts(" save <file>                       Save current HV settings to [file]");
-    puts(" exit                              Exit program");
-    puts(" rate <rate>                       Set status refresh rate to <rate> [Hz]");
-    puts(" timeout <time>                    Set timeout to return from read to <time> [s]");
-    puts(" reset                             Reset active HV board");
-    puts(" start                             Start HV status monitor");
-    puts(" stop                              Stop HV status monitor - not recommended!");
-    puts(" uptime                            Get program uptime [h:m:s]");
-    puts(" verbose <on|off>|                 Enable|disable verbosity");
-    puts(" help                              Print help");
-    puts(" .<cmd>                   	     Execute shell command <cmd>");
+    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"
+		" status [dac]                      Show status information (DAC values if requested)\n"
+		" config                            Print configuration\n"
+		" load <file>                       Load and set bias settings from <file>\n"
+		" save <file>                       Save current bias settings to [file]\n"
+		" exit                              Exit program\n"
+		" rate <rate>                       Set status refresh rate to <rate> [Hz]\n"
+		" timeout <time>                    Set timeout to return from read to <time> [s]\n"
+		" reset                             Reset active bias board\n"
+		" start                             Start bias status monitor\n"
+		" stop                              Stop bias status monitor - not recommended!\n"
+		" uptime                            Get program uptime [h:m:s]\n"
+		" help                              Print help\n"
+		" .<cmd>                   	     Execute shell command <cmd>");
 
     return;
@@ -206,5 +202,5 @@
 
 
-  // Set new high voltage (if no boards available, simply returns OK)
+  // 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")) {
@@ -249,19 +245,20 @@
     for (int i=FirstBoard; i<=LastBoard; i++) {
       if (i!=Board && Board!=-1) continue;
-
-      for (int j=FirstChain; j<=LastChain; j++) {
+    for (int j=FirstChain; j<=LastChain; j++) {
         if (j!=Chain && Chain!=-1) continue;
-
 	for (int k=0; k<NUM_CHANNELS; k++) {
 	  if (k!=Channel && Channel!=-1) continue;
 
-    	  // Convert from HV to DAC values
+	  // hvdiff is ignored if DAC value is zero
+	  if ((strlen(Param[0])>2 || isdigit(*Param[2])==0) && (fHVBoard[i]->HV[j][k] == 0)) continue;
+
+	  // Determine new DAC values
 	  if (!SetDac){
-	    if(strlen(Param[0]) > 2) fHVBoard[i]->HVV[j][k] += hvoltageV; // hvdiff
+		if (strlen(Param[0])>2 || isdigit(*Param[2])==0) fHVBoard[i]->HVV[j][k] += hvoltageV; // hvdiff
 	    else fHVBoard[i]->HVV[j][k] = hvoltageV;
 	    DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k);
 	  }
 	  else {
-	    if(strlen(Param[0]) > 2) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // hvdiff
+	    if(strlen(Param[0])>2 || isdigit(*Param[2])==0) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // hvdiff
 	    else DACValue = hvoltage;
 	  }
@@ -271,9 +268,9 @@
 	  if (SetDac) fHVBoard[i]->HVV[j][k] = calib->DACToHV(fHVBoard[i]->HV[j][k], i, j, k);
 
-    	  // Update DIM services
-    	  fHVBoard[i]->BiasVolt[j][k]->updateService();
+      // Update DIM services
+      fHVBoard[i]->BiasVolt[j][k]->updateService();
 
 	} // Channels	
-      } // Chains
+    } // Chains
     } // Boards
 
@@ -306,5 +303,5 @@
       for (int Board=0; Board<NumHVBoards; Board++) {
 	if (Match(fHVBoard[Board]->BoardName, Buffer)) {
-	  PrintMessage("Found HV settings for board %d (%s)\n\r",fHVBoard[Board]->GetBoardNumber(), fHVBoard[Board]->BoardName);
+	  PrintMessage("Found bias settings for board %d (%s)\n\r",fHVBoard[Board]->GetBoardNumber(), fHVBoard[Board]->BoardName);
 
 	  Chain = 0;  Channel = 0;
@@ -339,7 +336,7 @@
     	    
     if (NBoards != NumHVBoards) {
-      PrintMessage("Warning: Could not load HV settings for all connected HV boards\n");
-    }
-    else if (Errors == 0) PrintMessage("Success: Read HV settings for all connected HV boards\n");
+      PrintMessage("Warning: Could not load bias settings for all connected HV boards\n");
+    }
+    else if (Errors == 0) PrintMessage("Success: Read bias settings for all connected HV boards\n");
     if (Errors != 0) PrintMessage("Warning: Errors on %d channel(s) occurred\n", Errors);
     
@@ -406,5 +403,5 @@
     }
   
-    fprintf(File,"********** HV settings, %04d %02d %02d, %02d:%02d:%02d **********\n\n",
+    fprintf(File,"********** Bias settings, %04d %02d %02d, %02d:%02d:%02d **********\n\n",
 	    1900 + Time->tm_year, 1 + Time->tm_mon,
 	    Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec);
@@ -433,5 +430,5 @@
     state = active;
     pthread_kill(HVMonitor, SIGUSR1);
-    PrintMessage("Status monitoring activated\n");
+    PrintMessage(All, "Status monitoring activated\n");
     return;  
   }
@@ -442,9 +439,8 @@
     
     PrintMessage("\n Status monitor: %s\n", state_str[state]);
-    PrintMessage(" Verbose: %s\n", Verbose ? "on" : "off");
     PrintMessage(" Status refresh rate [Hz]: %.2f\n", fStatusRefreshRate);
     PrintMessage(" Socket state: %s\n", Socket==-1 ? "disconnected":"connected");
-    PrintMessage(" Total number of HV boards: %d\n", NumHVBoards);
-    PrintMessage(" Active HV boards: %d\n\n", LastBoard - FirstBoard + 1);
+    PrintMessage(" Total number of boards: %d\n", NumHVBoards);
+    PrintMessage(" Active boards: %d\n\n", LastBoard - FirstBoard + 1);
 
     for (int i=FirstBoard; i<=LastBoard; i++) {
@@ -479,5 +475,5 @@
     state = stopped;
     pthread_kill(HVMonitor, SIGUSR1);
-    PrintMessage("Status monitor stopped\n");
+    PrintMessage(All, "Status monitor stopped\n");
 
     return;
@@ -520,21 +516,4 @@
 
 
-  // Enable/disable verbosity
-  else if (Match(Param[0], "verbose")) {
-
-    if (Match(Param[1], "on")) {
-      Verbose = true;
-      PrintMessage("Verbosity enabled\n");
-    }    
-    else if (Match(Param[1], "off")) {
-      Verbose = false;
-      PrintMessage("Verbosity disabled\n");
-    }
-    else PrintMessage("Usage: verbose <on>|<off>\n");
-  
-    return;
-  }
-  
-  
   // Exit program
   else if(Match(Param[0], "exit")) {
@@ -559,5 +538,5 @@
 
 // Print message to selected target
-void ProcessIO::PrintMessage(int Target, const char *Format, ...) {
+void ProcessIO::PrintMessage(MsgTarget Target, const char *Format, ...) {
   va_list ArgumentPointer;
   va_start(ArgumentPointer, Format); 
@@ -570,6 +549,6 @@
   va_list ArgumentPointer;
   va_start(ArgumentPointer, Format);
-  if (CmdFromSocket) DoPrintMessage(Format, ArgumentPointer, MsgToSocket|MsgToLog);
-  else DoPrintMessage(Format, ArgumentPointer, MsgToConsole|MsgToLog);
+  if (CmdFromSocket) DoPrintMessage(Format, ArgumentPointer, Client);
+  else DoPrintMessage(Format, ArgumentPointer, Console);
   va_end(ArgumentPointer);
 }
@@ -577,7 +556,7 @@
 // Function doing the actual printing work
 // Be careful with overloading variadic functions!
-void ProcessIO::DoPrintMessage(const char *Format, va_list ArgumentPointer, int Target) {
-
-  char Textbuffer[MAX_COM_SIZE];
+void ProcessIO::DoPrintMessage(const char *Format, va_list ArgumentPointer, MsgTarget Target) {
+
+  static char Textbuffer[MAX_COM_SIZE]; // static because of DIM service
 
   memset(Textbuffer, 0, sizeof(Textbuffer));  
@@ -585,5 +564,5 @@
   
   // Print to console
-  if(Target & MsgToConsole) {
+  if(Target & Console) {
     if(strlen(Textbuffer)>0 && Textbuffer[strlen(Textbuffer)-1]=='\n') {
       printf("\r%s%s", Textbuffer, Prompt);   // New prompt
@@ -592,22 +571,26 @@
     fflush(stdout);
   }
+
+  // Send to DIM service
+  Textout->updateService(Textbuffer); 
+
   // Print to socket
-  if((Target & MsgToSocket) && Socket!=-1) {
+  if((Target & Client) && Socket!=-1) {
     write(Socket, Textbuffer, strlen(Textbuffer));
   }
-  // Print to log file (replace carriage return by linefeed)
-  if((Target & MsgToLog) && Logfile!=NULL) {
-    for (unsigned int i=0; i<strlen(Textbuffer); i++) {
-      if(Textbuffer[i] == '\r') Textbuffer[i] = '\n';
-    }
-    time_t Time;
-    strftime(Textbuffer+strlen(Textbuffer)+1,MAX_COM_SIZE-strlen(Textbuffer)-1, "%d/%m/%y %X", localtime(&(Time=time(NULL))));
-    fprintf(Logfile, "%s: %s", Textbuffer+strlen(Textbuffer)+1, Textbuffer);
-    fflush(Logfile);
-  }
-}
-
-
-// Ramp to new voltage with maximum step size given in config->fHVMaxDiff
+
+  // Send to log
+  if(Target & Log) {
+    char *Buf;
+    if (asprintf(&Buf, "%s %s", SERVER_NAME, Textbuffer) != -1) { 
+      DimClient::sendCommand("DColl/Log", Buf);
+      free(Buf);
+    }
+    else DimClient::sendCommand("DColl/Log", SERVER_NAME" asprintf() failed"); 
+  }
+}
+
+
+// Ramp to new voltage with maximum step size given in fHVMaxDiff
 // No ramping when decreasing voltage
 bool ProcessIO::RampVoltage(unsigned int Target, int Board, int Chain, int Channel) {
@@ -615,25 +598,12 @@
   while (fHVBoard[Board]->HV[Chain][Channel] != (int) Target) {	  
     int Diff = Target - fHVBoard[Board]->HV[Chain][Channel];
-    if (Diff > (int) config->fHVMaxDiff) Diff = config->fHVMaxDiff;
-
-    if (fHVBoard[Board]->SetHV(Chain, Channel, fHVBoard[Board]->HV[Chain][Channel]+Diff) == 1) {
-      if (Verbose) {
-	PrintMessage("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));
-	PrintBoardStatus(Board);
-      }
-    }
-    else {
-      PrintMessage("Error: Could not set HV of board %d, chain %d, channel %d. Skipping channel\n",fHVBoard[Board]->GetBoardNumber(),Chain,Channel);
-      SlowDataClass->NewEntry("Error");
-      SlowDataClass->AddToEntry("%s %d %d %d %d %.2f ",fHVBoard[Board]->BoardName,Board, Chain, Channel, Target, calib->DACToHV(Target,Board,Chain,Channel));
+    if (Diff > (int) fHVMaxDiff) Diff = fHVMaxDiff;
+
+    if (fHVBoard[Board]->SetHV(Chain, Channel, fHVBoard[Board]->HV[Chain][Channel]+Diff) != 1) {
+      State(ERROR, "Could not set bias of board %d, chain %d, channel %d. Skipping channel\n",fHVBoard[Board]->GetBoardNumber(),Chain,Channel);
       return false;
     }
   }
-  SlowDataClass->NewEntry("Value");
-  SlowDataClass->AddToEntry("%s %d %d %d %d %.2f ",fHVBoard[Board]->BoardName,Board, Chain, Channel, Target, calib->DACToHV(Target,Board,Chain,Channel));
-
-  // Update DIM service
-  fHVBoard[Board]->BiasDAC[Chain][Channel]->updateService();
-  
+
   return true;
 }
@@ -649,5 +619,6 @@
       if (!Warned) {
         Warned = true;
-        PrintMessage("Warning: Some board has many read/write errors, status monitor disabled\n");
+        PrintMessage(All, "Warning: Some board has many read/write errors, status monitor disabled\n");
+        State(WARN, "Warning: Some board has many read/write errors, status monitor disabled\n");
       }
       continue;
@@ -655,20 +626,24 @@
 
     if (fHVBoard[i]->GetStatus() != 1) {
-      PrintMessage("Error: Monitor could not read status of board %d\n", fHVBoard[i]->GetBoardNumber());
+      PrintMessage(All, "Error: Monitor could not read status of board %d\n", fHVBoard[i]->GetBoardNumber());
+      State(ERROR, "Error: Monitor could not read status of board %d\n", fHVBoard[i]->GetBoardNumber());
     }
     
     if (fHVBoard[i]->ResetButton) {
-      PrintMessage("Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber());
+      PrintMessage(All, "Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber());
+      State(INFO, "Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber());
       ResetBoard(i);
     }
     
     if (!fHVBoard[i]->WrapOK) {
-      PrintMessage("Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber());
+      PrintMessage(All, "Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber());
+      State(ERROR, "Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber());
     }
 
     for (int j=0; j<NUM_CHAINS; j++) {
       if (fHVBoard[i]->Overcurrent[j]) {
-	PrintMessage("Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber());
-	ResetBoard(i);
+		PrintMessage(All, "Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber());
+		State(WARN, "Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber());
+		ResetBoard(i);
       }
     }
@@ -724,4 +699,17 @@
 }
 
+//
+// 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());
+    pthread_mutex_unlock(&control_mutex);
+}
 
 // Check if two strings match (min 1 character must match)
Index: /hvcontrol/src/ProcessIO.h
===================================================================
--- /hvcontrol/src/ProcessIO.h	(revision 160)
+++ /hvcontrol/src/ProcessIO.h	(revision 161)
@@ -8,33 +8,40 @@
 #include <signal.h>
 
-#define SERVER_NAME "BIAS"       // Name to use in DIM
-#include "../../Evidence/Evidence.h"
+#define SERVER_NAME "Bias"       // Name to use in DIM
+#include "Evidence.h"
 
-#include "HVConfig.h"
 #include "HVCalib.h"
 #include "HV.h"
 #include "../pixelmap/PixelMap.h"
-#include "../drsdaq/SlowData.h"
+
+#define MAX_COM_SIZE 5000
+#define NUM_CHAINS 4
+#define NUM_CHANNELS 32
+#define BUFFER_LENGTH 256
+
+#define MIN_TIMEOUT 0.01
+#define MAX_TIMEOUT 5.0
+
+#define MIN_RATE 0.01
+#define MAX_RATE 50.0
 
 #define MAX_NUM_TOKEN 10
 
-#define MsgToConsole 1
-#define MsgToLog 2
-#define MsgToSocket 4
+enum MsgTarget {Console=1, Log=2, Client=4, All=7};
+typedef enum stateenum {active, stopped, na} state_enum;
 
-typedef enum stateenum { active, stopped, na } state_enum;
-
-class ProcessIO: public EvidenceServer {
+class ProcessIO: public DimCommand, public EvidenceServer {
 
   time_t StartTime;
-  FILE *Logfile;
   PixelMap *pm;
+  DimService *Textout;
+  
+  void commandHandler();
 
  public:
   
-  HVConfig    *config;
+  //HVConfig    *config;
   HVCalib     *calib;
   HVBoard **fHVBoard;
-  SlowData *SlowDataClass;
   
   pthread_mutex_t control_mutex;
@@ -44,10 +51,20 @@
   int NParam;
   bool CmdFromSocket;
-  
+
+  // Configuration data
+  char *fPixMapTable;
+  float fTimeOut;
+  float fStatusRefreshRate;
+  int fCCPort;
+  int DACMin;
+  int DACMax;
+  float fHVCalibOffset;
+  float fHVCalibSlope;
+  unsigned int fHVMaxDiff;
+
   // Status variables  
   pthread_t HVMonitor;       // exit function sends signal to these threads
   pthread_t SocketThread;
   
-  bool Verbose;  
   int Socket;                // -1 if not connected
 
@@ -58,5 +75,4 @@
   int LastChain;
   
-  float fStatusRefreshRate;
   state_enum   state;
   bool Exit;
@@ -66,7 +82,7 @@
   ~ProcessIO();
 
-  void PrintMessage(int, const char *, ...);
+  void PrintMessage(MsgTarget, const char *, ...);
   void PrintMessage(const char *, ...);
-  void DoPrintMessage(const char *, va_list, int);
+  void DoPrintMessage(const char *, va_list, MsgTarget);
   void CommandControl(char*);
   bool RampVoltage(unsigned int, int, int, int);
