Index: drsdaq/HVFeedback.cc
===================================================================
--- drsdaq/HVFeedback.cc	(revision 27)
+++ drsdaq/HVFeedback.cc	(revision 36)
@@ -17,12 +17,19 @@
 
 #define MAX_RETRY 5
-
+#define PIXMAP_LOCATION "../config/PixelMap.txt"
+
+//
 // Constructor: Initialise feedback 
+//
 HVFeedback::HVFeedback(DAQReadout* DAQClass, char* Configfile) {
   struct sockaddr_in SocketAddress;
-  
+  char Filename[MAX_PATH];
+
   m = DAQClass;
-  PixMap = new PixelMap("../config/PixelMap.txt", false);
-  
+  PixMap = new PixelMap(PIXMAP_LOCATION, false);
+
+  snprintf(Filename,sizeof(Filename),"%s/SlowData/", m->fRawDataPath);
+  SlowDataClass = new SlowData(m, "HVFB", Filename);
+
   // Read configuration file
   FILE *File;
@@ -32,15 +39,16 @@
   else {
     printf("Reading feedback configuration file %s\n", Configfile);
-    ReadCard("LedTrigBoard",       &fLedTrigBoard,      'I', File);
-    ReadCard("LedTrigChannel",     &fLedTrigChannel,    'I', File);
-    ReadCard("LedTrigChip",        &fLedTrigChip,       'I', File);
-    ReadCard("LedTrigSample",      &fLedTrigSample,     'I', File);
-    ReadCard("LedTrigThreshold",   &fLedTrigThreshold,  'f', File);
-    ReadCard("LedSignalSample",    &fLedSignalSample,   'I', File);
-    ReadCard("LedBaselineSample",  &fLedBaselineSample, 'I', File);
-    ReadCard("DefaultNumAverage",  &fDefaultNumAverage, 'I', File);
-    ReadCard("HVControlServer",     fHVControlServer,   's', File);
-    ReadCard("HVControlPort",      &fHVControlPort,     'I', File);
-    ReadCard("MaxCmdAckDelay",     &fMaxCmdAckDelay,    'I', File);
+    ReadCard("TrigBoard",           &fLedTrigBoard,      'I', File);
+    ReadCard("TrigChannel",         &fLedTrigChannel,    'I', File);
+    ReadCard("TrigChip",            &fLedTrigChip,       'I', File);
+    ReadCard("TrigSample",          &fLedTrigSample,     'I', File);
+    ReadCard("TrigThreshold",       &fLedTrigThreshold,  'f', File);
+    ReadCard("SignalSample",        &fLedSignalSample,   'I', File);
+    ReadCard("BaselineSample",      &fLedBaselineSample, 'I', File);
+    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);
     fclose(File);
   }
@@ -48,9 +56,17 @@
 
   // Initialise
-  Average    = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];
-  Response   = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];
-  Target     = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];
-  Buffer     = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];  
- 
+  Average    = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels]();
+  Sigma      = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels]();
+  Response   = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels]();
+  Target     = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels]();
+  Buffer     = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels]();  
+
+/*   for (int i=m->FirstBoard; i<=m->LastBoard; i++)
+    for (int j=0; j<kNumberOfChips; j++)
+      for (int k=0; k<kNumberOfChannels; k++) {
+        Response[i][j][k] = 0.0;
+    	Target[i][j][k] = 0.0;
+      } 
+ */
   Gain = 1;
   SetFBMode(FB_Off);
@@ -77,5 +93,7 @@
 }
 
+//
 // Destructor
+//
 HVFeedback::~HVFeedback() {
   if (SocketDescriptor!=-1) {
@@ -85,106 +103,141 @@
   delete[] Average;   	delete[] Response;
   delete[] Target;   	delete[] Buffer;
-  delete PixMap;
-}
-
-
+  delete SlowDataClass; delete PixMap;
+}
+
+//
 // Check if LED trigger present, if yes accumulate feedback data and
 // calculate new high voltages if the required number of events is reached.
+//
 bool HVFeedback::ProcessEvent() {
-  float Correction;
+  int i,j,k,q;
+  float Correction, Integral, Difference, EffectiveGain;
   
   // Check for LED trigger channel on given channel and if feedback running
   if (FBMode==FB_Off || m->WaveForm[fLedTrigBoard][fLedTrigChip][fLedTrigChannel][fLedTrigSample] < fLedTrigThreshold)
     return false;
-  Count++;
   
-  // Add signal at LED bin for all channels
-  for (int i=m->FirstBoard; i<=m->LastBoard; i++)
-    for (int j=0; j<kNumberOfChips; j++)
-      for (int k=0; k<kNumberOfChannels; k++)
-        Average[i][j][k] += (m->WaveForm[i][j][k][fLedSignalSample] - m->WaveForm[i][j][k][fLedBaselineSample])*m->BStruct[i].ScaleFactor;
-  
+  // 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++) 
+          Integral += (m->WaveForm[i][j][k][fLedSignalSample+q] - m->WaveForm[i][j][k][fLedBaselineSample+q])*m->BStruct[i].ScaleFactor;
+        Integral /= 2*fIntHalfWidth+1;
+	Average[i][j][k] += Integral;
+    	Sigma[i][j][k] += pow(Integral,2);
+      }
+
+  if (++Count<NumAverages) return false;
+
   // Acquired number of event requires action
-  if (Count==NumAverages) {
-    for (int i=m->FirstBoard; i<=m->LastBoard; i++)
-      for (int j=0; j<kNumberOfChips; j++)
-        for (int k=0; k<kNumberOfChannels; k++) {
-	  Average[i][j][k] /= Count;
-	  switch (FBMode) {
-	    case FB_Active:   // Determine correction from response maxtrix and change voltages
-              Correction = (Target[i][j][k] - Average[i][j][k])*Response[i][j][k]*Gain;
-              if(Target[i][j][k]!=0 && !PixMap->DRS_to_Pixel(i,j,k).empty())
-		WriteHVCommand("hvdiff %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];
-	      break;
-      	    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(), Voltage2);
-	      break;
-      	    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);
-		Response[i][j][k] = 0;
-	      }
-	      else Response[i][j][k] = Voltage2/(Buffer[i][j][k]-Average[i][j][k]);
-	      break;
-	    default: break;  // to suppress warning abount not handled enumeration value
-          }			
-        }
-    switch (FBMode) {
-      case FB_Active:
-      	m->PrintMessage("HV Feedback: Acted.\n");
-	break;
-      case FB_Targets:
-	m->PrintMessage("HV Feedback: New targets set, switching off.\n");
-	FBMode = FB_Off;
-	break;
-      case FB_ResponseFirst:
-        FBMode = FB_ResponseSecond;
-	m->PrintMessage("HV Feedback: Setting second voltage %f for response measurement, acquiring data.\n", Voltage2);
-	break;
-      case FB_ResponseSecond:
-	m->PrintMessage("HV Feedback: Response measurements finished, switching off.\n");
-	FBMode = FB_Off;
-	break;
-      default: break;  // to suppress warning abount not handled enumeration value
-    }			
-    ClearAverages();
-    return true;
-  }
-  else return false;   
-}
-
+  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
+  }			
+
+  for (i=m->FirstBoard; i<=m->LastBoard; i++)
+    for (j=0; j<kNumberOfChips; j++)
+      for (k=0; k<kNumberOfChannels; k++) {
+	Average[i][j][k] /= Count;
+	Sigma[i][j][k] = sqrt(Sigma[i][j][k]/Count-pow(Average[i][j][k],2))/sqrt(Count);
+	switch (FBMode) {
+	  case FB_Active:   // Determine correction from response maxtrix and change voltages
+    	    Difference = Target[i][j][k] - Average[i][j][k];
+	    EffectiveGain = Gain*pow(0.5*(1+(Difference/Sigma[i][j][k]-1)/(Difference/Sigma[i][j][k]+1)),2);
+	    Correction = -Difference*Response[i][j][k]*EffectiveGain;
+            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);
+	    }
+	    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  
+	    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);
+	    break;
+      	  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);
+	      Response[i][j][k] = 0;
+	    }
+	    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);
+	    break;
+	  default: break;  // to suppress warning abount not handled enumeration value
+        }			
+      }
+
+  switch (FBMode) {
+    case FB_Targets:
+      m->PrintMessage("HV Feedback: New targets set, switching off.\n");
+      FBMode = FB_Off;
+      break;
+    case FB_ResponseFirst:
+      FBMode = FB_ResponseSecond;
+      m->PrintMessage("HV Feedback: Increasing voltages by %f for response measurement, acquiring data.\n", DiffVoltage);
+      break;
+    case FB_ResponseSecond:
+      m->PrintMessage("HV Feedback: Response measurements finished, original voltages set, switching off.\n");
+      FBMode = FB_Off;
+      break;
+    default: break;  // to suppress warning abount not handled enumeration value
+  }
+  ClearAverages();
+  return true;  
+}
+
+//
 // Clear average values and event counter
+//
 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++) Average[i][j][k] = 0;
+      for (int k=0; k<kNumberOfChannels; k++) {
+        Average[i][j][k] = 0.0;
+	Sigma[i][j][k] = 0.0;
+      }
   Count = 0;
 }
 
+//
 // Number of events to accumulate before correction acts
+//
 void HVFeedback::SetNumAverages(unsigned int Averages) {
   NumAverages = Averages;
 }
 
+//
 // Get requested number of events
+//
 unsigned int HVFeedback::GetNumAverages() {
   return NumAverages;
 }
 
+//
 // Set feedback gain
+//
 void HVFeedback::SetGain(float FBGain) {
   Gain = FBGain;
 }
 
+//
 // Get feedback gain
+//
 float HVFeedback::GetGain() {
   return Gain;
 }
 
+//
 // Set feedback mode and clear averages
+//
 void HVFeedback::SetFBMode(FBState Mode) {
   if(Mode==FB_ResponseFirst || Mode==FB_ResponseFirst)
@@ -196,5 +249,7 @@
 }
 
+//
 // Set feedback mode and clear averages
+//
 FBState HVFeedback::GetFBMode() {
   switch (FBMode) {
@@ -208,10 +263,14 @@
 }
 
+//
 // Return current number of events
+//
 unsigned int HVFeedback::GetCurrentCount() {
   return Count;
 }
 
+//
 // Set target values
+//
 void HVFeedback::SetTarget(int Board, int Chip, int Channel, float TargetVal) {
   if(Board<m->NumCMCBoards && Chip<kNumberOfChips && Channel<kNumberOfChannels)
@@ -220,5 +279,7 @@
 }
 
+//
 // Print target values
+//
 void HVFeedback::GetTargets() {
   for (int i=m->FirstBoard; i<=m->LastBoard; i++)
@@ -228,9 +289,10 @@
 }
 
+//
 // Measure response matrix
-void HVFeedback::MeasureResponse(float U1, float U2) {
-
-  if (U2 == 0)
-    m->PrintMessage("HV Feedback: Error, econd voltage must not be zero.\n");
+//
+void HVFeedback::MeasureResponse(float U) {
+
+  if (U==0) m->PrintMessage("HV Feedback: Error, voltage difference must not non-zero.\n");
   else {
     for (int i=m->FirstBoard; i<=m->LastBoard; i++) 
@@ -238,22 +300,26 @@
         for (int k=0; k<kNumberOfChannels-2; k++) {
 	  if(PixMap->DRS_to_Pixel(i,j,k).empty()) m->PrintMessage("Could not find pixel ID of board %d, chip %d, channel %d\n",i,j,k);
-          else WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), U1);
+          else WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), -U/2);
         }
-    Voltage1 = U1;   Voltage2 = U2;
+    DiffVoltage = U;
     FBMode = FB_ResponseFirst;
     ClearAverages();  
-    m->PrintMessage("HV Feedback: Setting first voltage  %f for response measurement, acquiring data.\n",U1);
-  }
-}
-
+    m->PrintMessage("HV Feedback: Decreasing voltages by %f for response measurement, acquiring data.\n",DiffVoltage/2);
+  }
+}
+
+//
 // Print response values
+//
 void HVFeedback::GetResponse() {
   for (int i=m->FirstBoard; i<=m->LastBoard; i++)
     for (int j=0; j<kNumberOfChips; j++)
       for (int k=0; k<kNumberOfChannels; k++)
-         m->PrintMessage("Board %d, chip %d, channel %d: %f\n",i,j,k,Response[i][j][k]);
-}
-
+         m->PrintMessage("Board %d, chip %d, channel %d: %.3f\n",i,j,k,Response[i][j][k]);
+}
+
+//
 // Write commmand to socket
+//
 bool HVFeedback::WriteHVCommand(const char *Format, ...) {
   char Textbuffer[MAX_COM_SIZE];
@@ -263,7 +329,6 @@
   do {
     va_list ArgumentPointer;  va_start(ArgumentPointer, Format); 
-    vsprintf(Textbuffer, Format, ArgumentPointer);
-
-    printf("%s", Textbuffer);
+    vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer);
+
     // Write command to socket
     if(write(SocketDescriptor, Textbuffer, strlen(Textbuffer)+1)!=(int) strlen(Textbuffer)+1) {
@@ -295,13 +360,15 @@
 }
 
+//
 // Print feedback configuration
+//
 void HVFeedback::PrintConfig() {
   m->PrintMessage("LedTrigBoard: %d\t\tLedTrigChip: %d\t\tLedTrigChannel: %d\n"
         "LedTrigSample: %d\tLedTrigThreshold: %.2f\n"
         "LedSignalSample: %d\tLedBaselineSample: %d\tDefaultNumAverage: %d\n"
-        "HVControlServer: %s\tHVControlPort: %d\n"
+        "IntHalfWidth:%u\tHVControlServer: %s\tHVControlPort: %d\n"
 	"MaxCmdAckDelay: %d\n",
     fLedTrigBoard, fLedTrigChip, fLedTrigChannel, fLedTrigSample,
     fLedTrigThreshold, fLedSignalSample, fLedBaselineSample,
-    fDefaultNumAverage, fHVControlServer, fHVControlPort, fMaxCmdAckDelay);
-}
+    fDefaultNumAverage, fIntHalfWidth, fHVControlServer, fHVControlPort, fMaxCmdAckDelay);
+}
