Index: fact/FADctrl/FAD.cc
===================================================================
--- fact/FADctrl/FAD.cc	(revision 10100)
+++ fact/FADctrl/FAD.cc	(revision 10101)
@@ -32,5 +32,5 @@
    {"address", &FAD::cmd_address, true, 2, "<range> <value>", "Set addresses in range to value"},
    {"send", &FAD::cmd_send, true, 1, "<value>", "Set arbitrary data to board"},
-   {"acalib", &FAD::cmd_acalib, true, 0, "[n]", "Amplitude calibration (n events)"},
+   {"acalib", &FAD::cmd_acalib, true, 0, "[n|invalidate|file]", "Perform or read amplitude calibration (n events)"},
    //{"wmode", &FAD::cmd_wmode, 0, "<run|stop>", "Domino wave running or stopped during read out"},
    //{"rmode", &FAD::cmd_rmode, 0, "<first|stop>", "Readout start at first bin or stop position (DRS4)"},
@@ -61,10 +61,4 @@
   // DIM console service used in PrintMessage()
   ConsoleOut = new DimService(SERVER_NAME"/ConsoleOut", (char *) "");
-
-  // Get configuration data (static needed for c_str() pointers to remain valid after constructor finished)
-  //static string _CalibDataPath = GetConfig("CalibDataPath");
-  //fCalibDataPath = _CalibDataPath.c_str();
-
-  //snprintf(CalibInfoFilename,sizeof(CalibInfoFilename), "%s/CalibInfo", fCalibDataPath);
 
   // Construct boards
@@ -164,5 +158,5 @@
 	  // Check if idle mode required
 	  if (CommandList[i].NeedIdle && Mode != idle) {
-		PrintMessage("Current mode is not idle ('cancel' will stop current operation)");
+		PrintMessage("Current mode is not idle ('cancel' will stop current operation)\n");
 		return;
 	  }
@@ -449,5 +443,7 @@
 
   pthread_t Thread;
-  int Code;
+  int Code, Count;
+  FILE *File;
+  vector<string> Items;
 
   // Invalidate calibration?
@@ -456,5 +452,55 @@
 	return;
   }
-   
+
+  // Read calibration data from file?
+  if (Parameter.size() == 2 && !ConvertToInt(Parameter[1], &NumCalibEvents)) {
+    // Open file
+	if ((File = fopen(Parameter[1].c_str(), "r")) == NULL) {
+	  PrintMessage("Error opening file '%s'\n", Parameter[1].c_str());
+	  return;
+	} 
+	PrintMessage("Reading amplitude calibration information from file '%s'\n", Parameter[1].c_str());
+
+	// Read file into buffer and close file
+	string Buffer;
+    while (feof(File)==0 && ferror(File)==0) Buffer.push_back((char) fgetc(File));
+	if (Buffer.size() > 0) Buffer = Buffer.substr(0, Buffer.size()-1);
+	if (fclose(File) != 0) PrintMessage("Could not close file '%s'\n", Parameter[1].c_str());
+
+	// Search for calibration data for boards
+  	vector<string> Result = Tokenize(Buffer, "\n");
+
+	for (unsigned int Brd=0; Brd<Boards.size(); Brd++) {
+	  for (unsigned int Line=0; Line<Result.size(); Line++) {
+	    if (Result[Line].find(Boards[Brd]->Name) == string::npos) continue;
+
+		PrintMessage("Found calibration data for board '%s'\n", Boards[Brd]->Name);
+		Items = Tokenize(Result[Line]);
+		
+		// Check if correct number of items
+		if (Items.size() != NChips*NChannels*NBins*2 + 3) {
+		  PrintMessage("Error, data format invalid\n", Parameter[1].c_str());
+		  return;
+		}
+
+		// Extract data
+		Boards[Brd]->ACalibTemp = atof(Items[1].c_str());
+		Boards[Brd]->ACalibTime = atoi(Items[2].c_str());
+
+		Count = 3;
+		for (unsigned int i=0; i<NChips; i++) {
+		  for (unsigned int j=0; j<NChannels; j++) {
+			for (unsigned int k=0; k<NBins; k++) {
+			  Boards[Brd]->Baseline[i][j][k] = atoi(Items[Count++].c_str());
+			  Boards[Brd]->Gain[i][j][k] = atof(Items[Count++].c_str());
+			}
+		  }
+		}
+	  }
+	} // Loop over boards
+
+	return;
+  } // Reading calibration from file
+
   // Set number of events required for calibration
   if (Parameter.size()==1 || !ConvertToInt(Parameter[1], &NumCalibEvents) || NumCalibEvents<=0) {
@@ -518,5 +564,5 @@
 	struct FADBoard::BoardStatus S = Boards[i]->GetStatus();
 
-	PrintMessage("Board #%d (%sactive)    Communication %s\n", i, Boards[i]->Active ? "":"in", Boards[i]->CommError ? "ERROR":"OK");
+	PrintMessage("Board #%d - %s (%sactive)    Communication %s\n", i, Boards[i]->Name, Boards[i]->Active ? "":"in", Boards[i]->CommError ? "ERROR":"OK");
 	PrintMessage("DAC %d %d %d %d   %d %d %d %d\n", S.DAC[0], S.DAC[1], S.DAC[2], S.DAC[3], S.DAC[4], S.DAC[5], S.DAC[6], S.DAC[7] );
 	PrintMessage("Temperature %.2f %.2f %.2f %.2f", S.Temp[0], S.Temp[1], S.Temp[2], S.Temp[3]);
@@ -654,6 +700,4 @@
   /* Procedure
 
-  1. Register sampling frequency from FTM!
-  ...
   5. Issue single trigger and verify settings
   ...
@@ -682,5 +726,5 @@
 	Boards[Brd]->Send(&ROICmd[0], ROICmd.size()*sizeof(unsigned short));
 
-    // Set DAC first value
+    // Set first DAC value
     DACCmd[1] = htons(0);
     DACCmd[3] = htons(0);
@@ -688,10 +732,9 @@
 	Boards[Brd]->Send(DACCmd, sizeof(DACCmd));
 
-		// Switch off SCLK
-		//Boards[Brd]->Send(CMD_SCLK_OFF);
+	// Switch off SCLK
+	//Boards[Brd]->Send(CMD_SCLK_OFF);
 
 	// Start accumulation
     Boards[Brd]->AccumulateSum(NumCalibEvents);	
-	//Boards[Brd]->Send(CMD_Trigger_C);
   }
 
@@ -723,6 +766,6 @@
 	Boards[Brd]->Send(DACCmd, sizeof(DACCmd));
 
-		// Switch off SCLK
-		//Boards[Brd]->Send(CMD_SCLK_OFF);
+	// Switch off SCLK
+	//Boards[Brd]->Send(CMD_SCLK_OFF);
 
 	// Start accumulation
@@ -739,12 +782,9 @@
 	}
   }
-	for (unsigned int Brd=0; Brd<Boards.size(); Brd++) {
-		// Switch on SCLK
-		Boards[Brd]->Send(CMD_SCLK_ON);
-	}
 
   // Stop triggering, write back original ROI and DAC settings
   for (unsigned int Brd=0; Brd<Boards.size(); Brd++) {
-  	//Boards[Brd]->Send(CMD_Trigger_S);
+	// Switch on SCLK
+	Boards[Brd]->Send(CMD_SCLK_ON);
 
 	// Determine gain
@@ -773,19 +813,50 @@
   }
 
+  Mode = idle;
+  
+  if (Cancel) {
+    PrintMessage("Amplitude calibration cancelled\n");
+	return;
+  }
+ 
   PrintMessage("Amplitude calibration of all active boards finished, original ROI and DAC set\n");
-  Mode = idle;
-  
-  // Write short calibration information
-  /*time_t Time = time(NULL);
-  FILE *InfoFile = fopen(CalibInfoFilename, "w");
-  if (InfoFile != NULL) {
-	fprintf(InfoFile, "# Calibration information as of %s\n", ctime(&Time));
-	for (int i=0; i<GetNumberOfBoards(); i++) {
-	  fprintf(InfoFile, "%d %d %.1f %d %.2f\n", GetBoard(i)->GetBoardSerialNumber(), ACalib[i], ACalibTemp[i], TCalib[i], DRSFreq[i]);
-	}
-	fclose(InfoFile);
-  }
-  else PrintMessage("Could not write calibration information to file '%s'\n", CalibInfoFilename);
-*/
+  
+  // Write calibration data to file
+  time_t Time = time(NULL);
+  struct tm *TimeInfo;
+  char Buffer[200];
+
+  // Generate filename
+  TimeInfo = localtime(&Time);
+  if (strftime(Buffer, sizeof(Buffer), "/FADcalib_%y-%m-%jT%X.txt", TimeInfo) == 0) {
+	PrintMessage("Could not generate calibration data file name, strftime() failed\n");
+	return;
+  }
+  string Filename = string(getenv("HOME"))+Buffer;
+
+  FILE *File = fopen(Filename.c_str(), "w");
+  if (File == NULL) {
+	PrintMessage("Could not open calibration data file '%s'\n", Filename.c_str());
+	return;
+  }
+  
+  // Fix: Should actually contain serial number!
+  for (unsigned int Brd=0; Brd<Boards.size(); Brd++) {
+	fprintf(File, "\n%s: %f %d ", Boards[Brd]->Name, Boards[Brd]->ACalibTemp, (int) Boards[Brd]->ACalibTime);
+	for (unsigned int i=0; i<NChips; i++) {
+	  for (unsigned int j=0; j<NChannels; j++) {
+		for (unsigned int k=0; k<NBins; k++) {
+		  fprintf(File, "%d %lf ", Boards[Brd]->Baseline[i][j][k], Boards[Brd]->Gain[i][j][k]);
+		}
+	  }
+	}
+  }
+
+  // Close file	
+  if (fclose(File) != 0) {
+    PrintMessage("Could not close calibration file '%s'\n", Filename.c_str());
+  }
+  
+  PrintMessage("Wrote amplitude calibration information to file '%s'\n", Filename.c_str());
 }
 
@@ -896,5 +967,4 @@
 			if (Boards[Brd]->ACalibTime == -1) Data[Count++] = Boards[Brd]->Data[Chip][Chan][i];
 			else {
-			//Data[Count++] = (Boards[Brd]->Data[Chip][Chan][i] - Boards[Brd]->Baseline[Chip][Chan][(i+S.TriggerCell[Chip])%NBins]) * Boards[Brd]->Gain[Chip][Chan][(i+S.TriggerCell[Chip])%NBins];
 		      Temp = (Boards[Brd]->Data[Chip][Chan][i] - Boards[Brd]->Baseline[Chip][Chan][(i+S.TriggerCell[Chip])%NBins]);
 			  Temp *= Boards[Brd]->Gain[Chip][Chan][0]/Boards[Brd]->Gain[Chip][Chan][(i+S.TriggerCell[Chip])%NBins];
@@ -926,51 +996,6 @@
 }
 
+
 /*
-// Read calibration data
-bool FAD::ReadCalibration() {
-
-  static char Buffer[MAX_COM_SIZE];
-  int Serial, Calib;
-  float Temp, Freq;
-
-  for (int i=FirstBoard; i<=LastBoard; i++) {
-    if (GetBoard(i)->GetDRSType() == 4) {
-      if (ACalib[i] == false) {
-	    // Check calibration info file if EEPROM data on DRS board still valild
-		FILE *CalibInfo = fopen(CalibInfoFilename, "r");
-		if (CalibInfo == NULL) return false;
-		fgets(Buffer, sizeof(Buffer), CalibInfo); // skip first two lines
-		fgets(Buffer, sizeof(Buffer), CalibInfo);
-
-		while (fgets(Buffer, sizeof(Buffer), CalibInfo) != NULL) {
-		  if (sscanf(Buffer, "%d %d %f %*d %f", &Serial, &Calib, &Temp, &Freq) != 4) {
-			fclose(CalibInfo);
-			return false;
-		  }
-
-		  if (Serial==GetBoard(i)->GetBoardSerialNumber() && int(Freq*100)==int(DRSFreq[i]*100) && Calib==1) {
-			ACalib[i] = true;
-			ACalibTemp[i] = Temp;
-			break;
-		  }
-		}
-		fclose(CalibInfo);
-	  }
-    }
-    else {
-      if (!ACalib[i]) {
-        GetBoard(i)->SetCalibrationDirectory(fCalibDataPath);
-        PrintMessage("Reading response calibration file for board %d from: \"%s\"\n", i, fCalibDataPath);
-        for (int Chip=0; Chip<GetBoard(i)->GetNumberOfChips(); Chip++) {
-          if (GetBoard(i)->GetResponseCalibration()->ReadCalibration(Chip) == false) return false;
-        }
-        ACalib[i] = true;
-      }
-    }
-	if (fabs(ACalibTemp[i]-GetBoard(i)->GetTemperature())>2) PrintMessage("Warning: Large difference to calibration temperature for board %d\n", i);
-  } // Loop over boards
-  return true;
-}
-
 // Set DOMINO mode 
 void FAD::SetDOMINOMode(int mode) {
Index: fact/FADctrl/FAD.h
===================================================================
--- fact/FADctrl/FAD.h	(revision 10100)
+++ fact/FADctrl/FAD.h	(revision 10101)
@@ -21,4 +21,5 @@
 
 const int DEFAULT_NUM_CALIB_EVENTS = 100;
+const char CALIB_DIRECTORY[] = "~/";
 
 enum ModeType {idle, acalib, tcalib};
@@ -44,6 +45,4 @@
 
 	int NumCalibEvents;
-    //const char *fCalibDataPath;
-    //char CalibInfoFilename[MAX_PATH];
 	
 	std::vector<std::string> BoardList;
Index: fact/FADctrl/FADBoard.cc
===================================================================
--- fact/FADctrl/FADBoard.cc	(revision 10100)
+++ fact/FADctrl/FADBoard.cc	(revision 10101)
@@ -220,11 +220,9 @@
 	// Check if buffer starts with start_package_flag, remove data if not
 	Temp = 0;
-	while (ntohs(Header->start_package_flag) != 0xfb01 && Pos > 0) {
-	  memmove(Buffer, Buffer+1, Pos-1);
-	  Pos--;
-	  Temp++;
-	}
+	while (ntohs(*((unsigned short *) (Buffer+Temp))) != 0xfb01 && Temp<Pos) Temp++;
 	if (Temp != 0) {
-	  printf("Removed %d bytes because of start_package_flag not found\n", Temp);
+	  memmove(Buffer, Buffer+Temp, Pos-Temp);
+	  Pos -= Temp;
+	  m->PrintMessage("Removed %d bytes because of start_package_flag not found\n", Temp);
 	  continue;
 	}
Index: fact/FADctrl/FADBoard.h
===================================================================
--- fact/FADctrl/FADBoard.h	(revision 10100)
+++ fact/FADctrl/FADBoard.h	(revision 10101)
@@ -25,5 +25,4 @@
 	class FAD *m;
 	int Socket;
-	char *Name;
 	pthread_t Thread;
 	pthread_mutex_t Mutex;
@@ -69,4 +68,5 @@
 	void Unlock();
 
+	char *Name;
 	bool InitOK;
 	bool CommError;
Index: fact/FADctrl/FADctrl.cc
===================================================================
--- fact/FADctrl/FADctrl.cc	(revision 10100)
+++ fact/FADctrl/FADctrl.cc	(revision 10101)
@@ -5,9 +5,11 @@
 #include <stdio.h>
 #include <readline/history.h>
+#include <string>
 
 #include "FAD.h"
 
-const char READLINE_HIST_FILE[] = "/tmp/.history.FADctrl";
+using namespace std;
 
+const string READLINE_HIST_FILE = string(getenv("HOME"))+"/.history_FADctrl";
 void OpenOtherSockets();
 
@@ -22,5 +24,5 @@
   
   // Load history buffer
-  read_history(READLINE_HIST_FILE);
+  read_history(READLINE_HIST_FILE.c_str());
 
   system("clear");
@@ -73,7 +75,5 @@
   DimClient::sendCommand(SERVER_NAME"/Command", "dwrite on");
   DimClient::sendCommand(SERVER_NAME"/Command", "roi all 1024");
-  sleep (1);
 
-  //EmptySockets(SocketDescriptor, 8, 750000L);
   M.PrintMessage("Finished initalizing all boards\n");
   
@@ -100,6 +100,6 @@
   
   // Save history buffer  
-  int Ret = write_history(READLINE_HIST_FILE);
-  if (Ret != 0 ) printf("Error writing history file to '%s' (%s)\n", READLINE_HIST_FILE, strerror(Ret));
+  int Ret = write_history(READLINE_HIST_FILE.c_str());
+  if (Ret != 0 ) printf("Error writing history file to '%s' (%s)\n", READLINE_HIST_FILE.c_str(), strerror(Ret));
 
   // Terminate thread for other sockets  
Index: fact/FADctrl/History.txt
===================================================================
--- fact/FADctrl/History.txt	(revision 10100)
+++ fact/FADctrl/History.txt	(revision 10101)
@@ -3,2 +3,3 @@
 22/10/2010	First check-in of FADctrl. Initial version derived from drsdaq revision 10007.
 5/1/2011	First version of amplitude calibration (no secondary calibration, yet). New 'socketmode' command.
+13/1/2011	Amplitude calibration data is written to text file.
