Index: drsdaq/HVFeedback.cc
===================================================================
--- drsdaq/HVFeedback.cc	(revision 140)
+++ drsdaq/HVFeedback.cc	(revision 175)
@@ -12,34 +12,37 @@
 #include "PixelMap.h"
 
-#include <sys/socket.h>
-#include <netdb.h>
-#include <signal.h>
-
 #define PIXMAP_LOCATION "../config/PixelMap.txt"
 
+static const char* FBState_Description[] = {
+	"Feedback off",
+	"Feedback active",
+	"Feedback acquiring new targets",
+	"Feedback measuring response with first voltage",
+	"Feedback measuring response with second voltage"
+};
+
 //
 // Constructor: Initialise feedback 
 //
-HVFeedback::HVFeedback(DAQReadout* DAQClass, char* Configfile) {
-  struct sockaddr_in SocketAddress;
+HVFeedback::HVFeedback(DAQReadout* DAQClass, char* Configfile):
+			EvidenceServer(SERVER_NAME){
 
   m = DAQClass;
+  //fNumberOfChannels = m->fNumberOfChannels;
+  //fNumberOfChips = m->fNumberOfChips;
+  fNumberOfChannels = 10;
+  fNumberOfChips = 2;  
+  
   PixMap = new PixelMap(PIXMAP_LOCATION, false);
 
-  // Create instance of slow data class for feedback
-  SlowDataClass = new SlowData("HVFB", m->fSlowDataPath);
-  if (SlowDataClass->ErrorCode != 0) {
-    m->PrintMessage("Warning: Could not open feedback slowdata file (%s)\n", strerror(SlowDataClass->ErrorCode));
-  }
-  SlowDataClass->NewEntry("Average-Info", "Feedback regulation occurred: Board Chip Channel Average Sigma Correction-Value");
-  SlowDataClass->NewEntry("Target-Info", "New Target values acquired: Board Chip Channel Target Sigma");
-  SlowDataClass->NewEntry("Response-Info", "New response measurement: Board Chip Channel Response");
-
   // Initialise with zero content
-  Average    = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Sigma      = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Response   = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Target     = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Buffer     = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();  
+  Average    = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
+  Sigma      = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
+  Response   = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
+  Target     = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
+  Buffer     = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();  
+
+  DIMAverage = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
+  DIMSigma   = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
 
   // Read configuration file
@@ -59,37 +62,23 @@
     ReadCard("IntHalfWidth",        &fIntHalfWidth, 	 'U', File);
     ReadCard("DefaultNumAverage",   &fDefaultNumAverage, 'I', File);
-    ReadCard("HVControlServer",      fHVControlServer,   's', File);
-    ReadCard("HVControlPort",       &fHVControlPort,     'I', File);
-    ReadCard("MaxCmdAckDelay",      &fMaxCmdAckDelay,    'I', File);
-    ReadCard("DefaultResponse",      Response,      	 'f', File, m->NumBoards*kNumberOfChips*kNumberOfChannels);
-    ReadCard("DefaultTarget",        Target,      	 'f', File, m->NumBoards*kNumberOfChips*kNumberOfChannels);
+    ReadCard("DefaultResponse",      Response,      	 'f', File, m->NumBoards*fNumberOfChips*fNumberOfChannels);
+    ReadCard("DefaultTarget",        Target,      	 'f', File, m->NumBoards*fNumberOfChips*fNumberOfChannels);
     // Add also initial gain to configuration parameters
     fclose(File);
   }
   PrintConfig(MsgToLog);
- 
+
+  // Provide DIM services
+  FeedbackAverage = new DimService (SERVER_NAME"/Average", "F", DIMAverage, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
+  FeedbackSigma = new DimService (SERVER_NAME"/Sigma", "F", DIMSigma, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
+  FeedbackResponse = new DimService (SERVER_NAME"/Response", "F", Response, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
+  FeedbackTarget = new DimService (SERVER_NAME"/Target", "F", Target, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
+  CountService = new DimService (SERVER_NAME"/Count", Count);
+
   // Initial state
   Gain = 0.2;
   SetFBMode(FB_Off);
   SetNumAverages(fDefaultNumAverage);
-
-  // Opening socket client to HV control program
-  if ((SocketDescriptor = socket(PF_INET, SOCK_STREAM, 0)) == -1)
-    m->PrintMessage("Could not open client socket, no HV control available.\n");
-
-  // Resolve hostname and try to connect to server
-  struct hostent *hostent = gethostbyname(fHVControlServer);
-  if (hostent==0)
-    m->PrintMessage("Could not resolve HV server host name \"%s\".\n", fHVControlServer);
-  else {
-    SocketAddress.sin_family = PF_INET;
-    SocketAddress.sin_port = htons((unsigned short) fHVControlPort);
-    SocketAddress.sin_addr = *(struct in_addr*) hostent->h_addr;
-  
-    if (connect(SocketDescriptor, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress))==-1)
-      m->PrintMessage("Could not connect to HV server %s at port %d (%s)\n", fHVControlServer, fHVControlPort, strerror(errno));
-    else m->PrintMessage("\nFeedback connected to HV server %s (port %d).\n", fHVControlServer, fHVControlPort);
-    signal(SIGPIPE,SIG_IGN);  // Do not kill process if writing to closed socket
-  }
+  LastServiceUpdate = 0;
 }
 
@@ -98,11 +87,14 @@
 //
 HVFeedback::~HVFeedback() {
-  if (SocketDescriptor!=-1) {
-    close(SocketDescriptor);
-    m->PrintMessage("Feedback socket closed.\n");
-  }
+
+  delete CountService;
+  delete FeedbackAverage;
+  delete FeedbackSigma;
+  delete FeedbackResponse;
+  delete FeedbackTarget;
+
   delete[] Average;   	delete[] Response;
   delete[] Target;   	delete[] Buffer;
-  delete SlowDataClass; delete PixMap;
+  delete PixMap;
 }
 
@@ -113,63 +105,66 @@
 bool HVFeedback::ProcessEvent() {
   int i,j,k,q;
-  float Correction, Integral, Difference;
+  float Correction, Integral;
   
   // Check for LED trigger channel on given channel and if feedback running
-  if (FBMode==FB_Off || m->WaveForm[fLedTrigBoard][fLedTrigChip][fLedTrigChannel][(fLedTrigSample+m->TriggerCell[fLedTrigBoard][fLedTrigChip])%kNumberOfBins] < fLedTrigThreshold)
+  if (FBMode==FB_Off || m->WaveForm[fLedTrigBoard][fLedTrigChip][fLedTrigChannel][(fLedTrigSample+m->TriggerCell[fLedTrigBoard][fLedTrigChip])%kNumberOfBins] < fLedTrigThreshold) {
     return false;
+  }
   
   // Calculate average signal of LED pulse as integral of signal
-  for (i=m->FirstBoard; i<=m->LastBoard; i++)
-    for (j=0; j<kNumberOfChips; j++)
-      for (k=0; k<kNumberOfChannels; k++) {
-	for (Integral=0, q=-fIntHalfWidth; q<=(int) fIntHalfWidth; q++) 
+  for (i=m->FirstBoard; i<=m->LastBoard; i++) {
+	for (j=0; j<fNumberOfChips; j++) {
+	  for (k=0; k<fNumberOfChannels; k++) {
+		for (Integral=0, q=-fIntHalfWidth; q<=(int) fIntHalfWidth; q++) { 
           Integral += (m->WaveForm[i][j][k][(fLedSignalSample+q+m->TriggerCell[i][j])%kNumberOfBins] - m->WaveForm[i][j][k][(fLedBaselineSample+q+m->TriggerCell[i][j])%kNumberOfBins])*m->drs->GetBoard(i)->GetPrecision();
+		}
         Integral /= 2*fIntHalfWidth+1;
-	Average[i][j][k] += Integral;
+		Average[i][j][k] += Integral;
     	Sigma[i][j][k] += pow(Integral,2);
       }
-
+	}
+  }
+  
+  // Update DIM service regularly
+  if (time(NULL)-LastServiceUpdate > 2) {
+    LastServiceUpdate = time(NULL);
+	CountService->updateService();
+  }
   // Check if acquired number of event requires action
   if (++Count<NumAverages) return false;
 
-  // Make entry in slow data file
-  switch (FBMode) {
-    case FB_Active: SlowDataClass->NewEntry("Average");
-    	    	    break;
-    case FB_Targets: SlowDataClass->NewEntry("Target");
-    	    	     break;
-    case FB_ResponseSecond: SlowDataClass->NewEntry("Response");
-    	    	    	    SlowDataClass->AddToEntry("%.3f ",DiffVoltage);
-			    break;
-    default: break;  // to suppress warning abount not handled enumeration value
-  }			
-
   // Feedback action
   for (i=m->FirstBoard; i<=m->LastBoard; i++) {
-    for (j=0; j<kNumberOfChips; j++) {
-      for (k=0; k<kNumberOfChannels; k++) {
+  for (j=0; j<fNumberOfChips; j++) {
+  for (k=0; k<fNumberOfChannels; k++) {
+    // Calculate average
 	Average[i][j][k] /= Count;
 	Sigma[i][j][k] = sqrt(Sigma[i][j][k]/Count-pow(Average[i][j][k],2))/sqrt(Count);
+	DIMAverage[i][j][k] = Average[i][j][k];
+	DIMSigma[i][j][k] = Sigma[i][j][k];
+	
 	switch (FBMode) {
 	  case FB_Active:   // Determine correction from response maxtrix and change voltages
-    	    Difference = Target[i][j][k] - Average[i][j][k];
-	    Correction = -Difference*Response[i][j][k]*Gain;
-    	    //if (fabs(Correction) > 0.1) Correction = fabs(Correction)/Correction*0.1;   // Limit changes to 100 mV
-            if(Correction!=0 && Target[i][j][k]!=0 && !PixMap->DRS_to_Pixel(i,j,k).empty()) {
-              printf("Average of board %d, chip %d, channel %d is %.2f +/- %.2f    Correction %.3f\n",i,j,k,Average[i][j][k],Sigma[i][j][k],Correction);
-	      SlowDataClass->AddToEntry("%d %d %d %.3f %.3f %.3f ", i,j,k,Average[i][j][k],Sigma[i][j][k],Correction);
-	      if(fabs(Average[i][j][k]) < 2*Sigma[i][j][k]) printf("Too noisy!\n");
-    	      else WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(),Correction);
-	    }
+	    Correction = -(Target[i][j][k] - Average[i][j][k])*Response[i][j][k]*Gain;
+    	if (fabs(Correction) > 0.1) Correction = fabs(Correction)/Correction*0.1;   // Limit changes to 100 mV
+        if(Correction==0 || Target[i][j][k] ==0 || PixMap->DRS_to_Pixel(i,j,k).empty()) break;
+
+        printf("Average of board %d, chip %d, channel %d is %.2f +/- %.2f    Correction %.3f\n",i,j,k,Average[i][j][k],Sigma[i][j][k],Correction);
+
+		if(fabs(Average[i][j][k]) < 2*Sigma[i][j][k]) printf("Too noisy!\n");
+		else WriteHVCommand("hv %s %+f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), Correction);
+
 	    break;
+
 	  case FB_Targets:  // Take average as new targets  
 	    Target[i][j][k] = Average[i][j][k];
- 	    SlowDataClass->AddToEntry("%d %d %d %.3f %.3f ", i,j,k,Average[i][j][k],Sigma[i][j][k]);
 	    break;
-      	  case FB_ResponseFirst:  // First point of response measurement done  
+
+	  case FB_ResponseFirst:  // First point of response measurement done  
 	    Buffer[i][j][k] = Average[i][j][k];
-	    if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hvdiff %s %f",PixMap->DRS_to_Pixel(i,j,k).c_str(), DiffVoltage);
+	    if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hv %s %+f",PixMap->DRS_to_Pixel(i,j,k).c_str(), DiffVoltage);
 	    break;
-      	  case FB_ResponseSecond: // Determine response from signal variation
+
+	  case FB_ResponseSecond: // Determine response from signal variation
 	    if(Buffer[i][j][k] == Average[i][j][k]) {
 	      m->PrintMessage("HV Feedback: Warning, response singular for board %d, chip %d, channel %d.\n",i,j,k);
@@ -177,32 +172,34 @@
 	    }
 	    else Response[i][j][k] = DiffVoltage/(Buffer[i][j][k]-Average[i][j][k]);
-	    SlowDataClass->AddToEntry("%d %d %d %.3f ", i,j,k,Response[i][j][k]);
-	    if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hvdiff %s %f",PixMap->DRS_to_Pixel(i,j,k).c_str(), -DiffVoltage/2);
+	    if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hv %s %+f",PixMap->DRS_to_Pixel(i,j,k).c_str(), -DiffVoltage/2);
 	    break;
+
 	  default: break;  // to suppress warning abount not handled enumeration value
         }			
-      }
-    }
-  }
-  
+  } // for() channels
+  } // for() chips
+  } // for() boards
+
+  // Update DIM service
+  FeedbackAverage->updateService();
+  FeedbackSigma->updateService();
+
   switch (FBMode) {
     case FB_Targets:
+	  FeedbackTarget->updateService();
       m->PrintMessage("HV Feedback: New targets set, switching off.\n");
-      FBMode = FB_Off;
+      SetFBMode(FB_Off, true);
       break;
     case FB_ResponseFirst:
-      FBMode = FB_ResponseSecond;
+      SetFBMode(FB_ResponseSecond, true);
       m->PrintMessage("HV Feedback: Increasing voltages by %f for response measurement, acquiring data.\n", DiffVoltage);
       break;
     case FB_ResponseSecond:
+	  FeedbackResponse->updateService();
       m->PrintMessage("HV Feedback: Response measurements finished, original voltages set, switching off.\n");
-      FBMode = FB_Off;
+      SetFBMode(FB_Off, true);
       break;
     default: break;  // to suppress warning abount not handled enumeration value
   }
-  
-  if(m->SlowDataClass->ErrorCode != 0) {
-    m->PrintMessage("Error, could not write feedback slow data to file (%s), file closed.\n", strerror(m->SlowDataClass->ErrorCode));
-  }
   ClearAverages();
   
@@ -215,10 +212,11 @@
 void HVFeedback::ClearAverages() {
   for (int i=m->FirstBoard; i<=m->LastBoard; i++)
-    for (int j=0; j<kNumberOfChips; j++)
-      for (int k=0; k<kNumberOfChannels; k++) {
+    for (int j=0; j<fNumberOfChips; j++)
+      for (int k=0; k<fNumberOfChannels; k++) {
         Average[i][j][k] = 0.0;
-	Sigma[i][j][k] = 0.0;
+		Sigma[i][j][k] = 0.0;
       }
   Count = 0;
+  CountService->updateService();
 }
 
@@ -254,9 +252,11 @@
 // Set feedback mode and clear averages
 //
-void HVFeedback::SetFBMode(FBState Mode) {
-  if(Mode==FB_ResponseFirst || Mode==FB_ResponseFirst)
+void HVFeedback::SetFBMode(FBState Mode, bool Internal) {
+  if((Mode==FB_ResponseFirst || Mode==FB_ResponseFirst) && !Internal)
       m->PrintMessage("Start reponse measurement by calling MeasureResponse().\n");
   else {
     FBMode = Mode;
+	if (Mode != FB_ResponseFirst) State(INFO, "%s", FBState_Description[FBMode]);
+	else State(INFO, "%s (voltage difference %.3f)", FBState_Description[FBMode], DiffVoltage);
     ClearAverages();
   }
@@ -267,12 +267,7 @@
 //
 FBState HVFeedback::GetFBMode() {
-  switch (FBMode) {
-    case FB_Off: m->PrintMessage("Feedback off.\n");   break;
-    case FB_Active: m->PrintMessage("Feedback active.\n");   break;
-    case FB_Targets: m->PrintMessage("Feedback acquiring new targets.\n");   break;
-    case FB_ResponseFirst: m->PrintMessage("Feedback measuring response with first voltage.\n");   break;
-    case FB_ResponseSecond: m->PrintMessage("Feedback measuring response with second voltage.\n");   break; 
-  }
-  return FBMode;			
+
+  m->PrintMessage("%s.\n", FBState_Description[FBMode]);
+  return FBMode;
 }
 
@@ -288,6 +283,8 @@
 //
 void HVFeedback::SetTarget(int Board, int Chip, int Channel, float TargetVal) {
-  if(Board<m->NumBoards && Chip<kNumberOfChips && Channel<kNumberOfChannels)
+  if(Board<m->NumBoards && Chip<fNumberOfChips && Channel<fNumberOfChannels) {
     Target[Board][Chip][Channel] = TargetVal;
+	FeedbackTarget->updateService();
+  }
   else printf("Invalid board, chip or channel number.\n");
 }
@@ -298,7 +295,7 @@
 void HVFeedback::GetTargets() {
   for (int i=m->FirstBoard; i<=m->LastBoard; i++)
-    for (int j=0; j<kNumberOfChips; j++) {
+    for (int j=0; j<fNumberOfChips; j++) {
       m->PrintMessage("Board %d, chip %d:",i,j);
-      for (int k=0; k<kNumberOfChannels; k++) m->PrintMessage(" %.2f",Target[i][j][k]);
+      for (int k=0; k<fNumberOfChannels; k++) m->PrintMessage(" %.2f",Target[i][j][k]);
       m->PrintMessage("\n\r");
     }
@@ -316,13 +313,12 @@
 
   for (int i=m->FirstBoard; i<=m->LastBoard; i++) 
-    for (int j=0; j<kNumberOfChips; j++) 
-      for (int k=0; k<kNumberOfChannels; k++) {
-	if(!PixMap->DRS_to_Pixel(i,j,k).empty()) {
-          WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), -U/2);
+    for (int j=0; j<fNumberOfChips; j++) 
+      for (int k=0; k<fNumberOfChannels; k++) {
+		if(!PixMap->DRS_to_Pixel(i,j,k).empty()) {
+          WriteHVCommand("hv %s %+f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), -U/2);
     	}
       }
   DiffVoltage = U;
-  FBMode = FB_ResponseFirst;
-  ClearAverages();  
+  SetFBMode(FB_ResponseFirst, true);
   m->PrintMessage("HV Feedback: Decreasing voltages by %f for response measurement, acquiring data.\n",DiffVoltage/2);
 }
@@ -333,7 +329,7 @@
 void HVFeedback::GetResponse() {
   for (int i=m->FirstBoard; i<=m->LastBoard; i++) {
-    for (int j=0; j<kNumberOfChips; j++) {
+    for (int j=0; j<fNumberOfChips; j++) {
       m->PrintMessage("Board %d, chip %d:",i,j);
-      for (int k=0; k<kNumberOfChannels; k++) m->PrintMessage(" %.3f",Response[i][j][k]);
+      for (int k=0; k<fNumberOfChannels; k++) m->PrintMessage(" %.3f",Response[i][j][k]);
       m->PrintMessage("\n\r");
     }
@@ -342,40 +338,15 @@
 
 //
-// Write commmand to socket
+// Write bias voltage commmand
 //
 bool HVFeedback::WriteHVCommand(const char *Format, ...) {
+
   char Textbuffer[MAX_COM_SIZE];
-  fd_set SelectDescriptor;
   
   va_list ArgumentPointer;  va_start(ArgumentPointer, Format); 
   vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer);
 
-  // Write command to socket
-  if(write(SocketDescriptor, Textbuffer, strlen(Textbuffer)+1)!=(int) strlen(Textbuffer)+1) {
-    m->PrintMessage("Error: Could not write (entire) command to HV socket (%s)\n", strerror(errno));
-    return false;
-  }
-
-  // Wait for command acknowledge from hvcontrol program
-  FD_ZERO(&SelectDescriptor);   FD_SET(SocketDescriptor, &SelectDescriptor);
-  struct timeval WaitTime = {fMaxCmdAckDelay, 0};
-  if (select(((int) SocketDescriptor)+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
-    m->PrintMessage("Error with select() in command acknowledge (%s)\n", strerror(errno));
-    return false;
-  }
-  
-  // Evaluate response
-  if (!FD_ISSET(SocketDescriptor, &SelectDescriptor)) { // Time-out
-    m->PrintMessage("Time-out of %d seconds expired before receiving acknowledge from HV socket.\n", fMaxCmdAckDelay);
-    return false;
-  }
-  if (read(SocketDescriptor, Textbuffer, MAX_COM_SIZE) == -1) { // Could not read
-    m->PrintMessage("Error reading acknowledge from HV socket (%s)\n", strerror(errno));
-    return false;
-  }
-  if (strncmp(Textbuffer, "OK", 2) != 0) { // ERROR response
-    m->PrintMessage("Did not received OK from hvcontrol.\n");
-    return false;
-  }
+  DimClient::sendCommand("Bias/Command", Textbuffer);
+
   return true;
 }
@@ -385,11 +356,11 @@
 //
 void HVFeedback::PrintConfig(int Target) {
+
   m->PrintMessage(Target, "LedTrigBoard: %d\t\tLedTrigChip: %d\t\tLedTrigChannel: %d\n"
         "LedTrigSample: %d\tLedTrigThreshold: %.2f\n"
         "LedSignalSample: %d\tLedBaselineSample: %d\tDefaultNumAverage: %d\n"
-        "IntHalfWidth:%u\tHVControlServer: %s\tHVControlPort: %d\n"
-	"MaxCmdAckDelay: %d\n",
+        "IntHalfWidth:%u\n",
     fLedTrigBoard, fLedTrigChip, fLedTrigChannel, fLedTrigSample,
     fLedTrigThreshold, fLedSignalSample, fLedBaselineSample,
-    fDefaultNumAverage, fIntHalfWidth, fHVControlServer, fHVControlPort, fMaxCmdAckDelay);
-}
+    fDefaultNumAverage, fIntHalfWidth);
+}
