Index: fact/FADctrl/FAD.cc
===================================================================
--- fact/FADctrl/FAD.cc	(revision 10187)
+++ fact/FADctrl/FAD.cc	(revision 10212)
@@ -70,4 +70,5 @@
   // Initialise configuration information (later non-blocking access in commandHandler())
   GetConfig("CalibTempDiffWarn", "0");
+  GetConfig("CalibFreqDiffWarn", "0");
 
   // Construct boards
@@ -492,14 +493,16 @@
 
   // Check conditions for run of all active boards
-  float MaxDiff = atof(GetConfig("CalibTempDiffWarn").c_str());
+  float MaxTempDiff = atof(GetConfig("CalibTempDiffWarn").c_str());
+  float MaxFreqDiff = atof(GetConfig("CalibFreqDiffWarn").c_str());
 
   for (unsigned int i=0; i<Boards.size(); i++) {
 	if (!Boards[i]->Active) continue;
 
-	if (Boards[i]->ACalibTime == -1) PrintMessage("Warning: Amplitude calibration missing for board %d\n", i);
+	if (Boards[i]->ACalib.Time == -1) PrintMessage("Warning: Amplitude calibration missing for board %d\n", i);
 	else {
 	  Temp = 0;
 	  for (unsigned int j=0; j<NTemp; j++) Temp += Boards[i]->GetStatus().Temp[j] / NTemp;
-	  if (fabs(Boards[i]->ACalibTemp-Temp) > MaxDiff) PrintMessage("Warning: Amplitude calibration to current temperature difference larger than %.1f K for board %d\n", MaxDiff, i);
+	  if (fabs(Boards[i]->ACalib.Temp-Temp) > MaxTempDiff) PrintMessage("Warning: Calibration to current temperature difference larger than %.1f K for board %d\n", MaxTempDiff, i);
+	  if (fabs(Boards[i]->ACalib.Frequency-Boards[i]->GetStatus().Frequency) > MaxFreqDiff) PrintMessage("Warning: Calibration to current frequency difference larger than %.1f GHz for board %d\n", MaxFreqDiff, i);
 	}
   }
@@ -515,11 +518,7 @@
 void FAD::cmd_acalib() {
 
-  int Count;
-  FILE *File;
-  vector<string> Items;
-
   // Invalidate calibration?
   if (Parameter.size() == 2 && Match(Parameter[1], "invalidate")) {
-	for (unsigned int i=0; i<Boards.size(); i++) Boards[i]->ACalibTime = -1;
+	for (unsigned int i=0; i<Boards.size(); i++) Boards[i]->ACalib.Time = -1;
 	return;
   }
@@ -527,4 +526,7 @@
   // Read calibration data from file?
   if (Parameter.size() == 2 && !ConvertToInt(Parameter[1], &NumEventsRequested)) {
+	FILE *File;
+	struct FADBoard::CalibData Data;
+
     // Open file
 	if ((File = fopen(Parameter[1].c_str(), "r")) == NULL) {
@@ -532,45 +534,13 @@
 	  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);
+	// Read data and check if it applies to any board
+	while (fread(&Data, sizeof(Data), 1, File) == 1) {
+	  for (unsigned int i=0; i<Boards.size(); i++) if (Data.DNA == Boards[i]->GetStatus().DNA) {
+	    PrintMessage("Found calibration data for board %d (%s)\n", i, ctime(&Data.Time));
+	    Boards[i]->ACalib = Data;
+	  }
+	}
+	//Close file
 	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*3 + 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());
-			  Boards[Brd]->SecondaryBaseline[i][j][k] = atof(Items[Count++].c_str());
-			}
-		  }
-		}
-	  }
-	} // Loop over boards
-
 	return;
   } // Reading calibration from file
@@ -602,12 +572,13 @@
 	}	  
 
-	PrintMessage("\rTotal boards: %d    (%d communication errors)     Active boards: %d\n", Boards.size(), Error, Count);
+	PrintMessage("\rTotal boards: %d    (%d communication errors)\n", Boards.size(), Error);
 
 	// Print list of active boards
-	if (Count != 0) {
-	  PrintMessage("Active are ");
-	  for (unsigned int i=0; i<Boards.size(); i++) if (Boards[i]->Active) PrintMessage(" %d", i);
-	  PrintMessage("\n");
-	}
+	PrintMessage("Active are %d boards(s)   ", Count);
+	for (unsigned int i=0; i<Boards.size(); i++) {
+	  if (Boards[i]->Active) PrintMessage(" %d", i);
+	  if (!Boards[i]->Active) PrintMessage("!");
+	}
+	PrintMessage("\n");
 
 	// Current mode
@@ -633,6 +604,6 @@
 
 	// Calibration information
-	if (Boards[i]->ACalibTime == -1) PrintMessage("No amplitude calibration available\n");
-	else PrintMessage("Calibration temperature %.1f     Calibration time %s" , Boards[i]->ACalibTemp, ctime(&Boards[i]->ACalibTime));
+	if (Boards[i]->ACalib.Time == -1) PrintMessage("No amplitude calibration available\n");
+	else PrintMessage("Calibration data: Temperature %.1f     Frequency %.2f     Time %s" , Boards[i]->ACalib.Temp, Boards[i]->ACalib.Frequency, ctime(&Boards[i]->ACalib.Time));
 
 	// Status information
@@ -645,5 +616,10 @@
 	PrintMessage("Last event received %s", ctime(&S.Update.tv_sec));
 
-	PrintMessage("Board ID %d		Firmware revision %d\n", S.BoardID, S.FirmwareRevision);
+	// Board identification
+	PrintMessage("Board ID %d      Firmware revision %d      Serial %llx\n", S.BoardID, S.FirmwareRevision, S.DNA);
+	PrintMessage("Board time %d      Event counter %d\n", S.BoardTime, S.EventCounter);
+
+	// Slow data
+	PrintMessage("Frequency %.2f GHz    Phase shift %d    PLL lock %d %d %d %d\n", S.Frequency, S.PhaseShift, S.Lock[0], S.Lock[1], S.Lock[2], S.Lock[3]);
 	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,7 +630,5 @@
 	}
 	PrintMessage("\n");
-	/*PrintMessage("Serial %d, firmware %d\n"
-		    GetBoard(i)->GetBoardSerialNumber(),
-
+	/*
 	if (GetBoard(i)->GetStatusReg() & BIT_RUNNING)
 	  PrintMessage("   Domino wave running\n");
@@ -799,6 +773,5 @@
 //
 // Exit programm
-// SIGTERM sets ExitRequest flag, and also makes
-// readline() return (in case command came over network)
+// SIGTERM makes readline() return (in case command came over network)
 //
 void FAD::cmd_exit() {
@@ -806,4 +779,8 @@
   if (Mode != idle) cmd_stop();
 
+  ExitRequest = true;
+
+  // Wait to allow console input to arrive at readline()
+  usleep(10000);
   pthread_kill(MainThread, SIGTERM);
 }
@@ -830,18 +807,8 @@
   PrintMessage("Amplitude calibration of all active boards finished, original ROI and DAC set\n");
   
-  // 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-%dT%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");
+  // Open calibration data file
+  string Filename = string(getenv("HOME"))+"/FAD_ACal";
+  FILE *File = fopen(Filename.c_str(), "ab");
+
   if (File == NULL) {
 	PrintMessage("Could not open calibration data file '%s'\n", Filename.c_str());
@@ -849,22 +816,16 @@
   }
   
-  // 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 %lf ", Boards[Brd]->Baseline[i][j][k], Boards[Brd]->Gain[i][j][k], Boards[Brd]->SecondaryBaseline[i][j][k]);
-		}
-	  }
+  // Write calibration information
+  for (unsigned int i=0; i<Boards.size(); i++) {
+	if (fwrite(&Boards[i]->ACalib, sizeof(Boards[i]->ACalib), 1, File) != 1) {
+	  PrintMessage("Could not write to calibration file '%s'\n", Filename.c_str());
+	  break;
 	}
   }
 
   // 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());
+  if (fclose(File) != 0) PrintMessage("Could not close calibration file '%s'\n", Filename.c_str());
+  
+  PrintMessage("Appended amplitude calibration information to file '%s'\n", Filename.c_str());
 }
 
@@ -1002,5 +963,5 @@
 	  S = Boards[Brd]->GetStatus();
 	  BStruct[Brd]->SerialNo = S.BoardID;
-	  BStruct[Brd]->NomFreq = 2;
+	  BStruct[Brd]->NomFreq = S.Frequency;
 	  BStruct[Brd]->BoardTemp = 0;        
 	  for (unsigned int i=0; i<NTemp; i++) BStruct[Brd]->BoardTemp += S.Temp[i]/NTemp;
@@ -1024,9 +985,9 @@
 	  for (unsigned int Chip=0; Chip<NChips; Chip++) for (unsigned int Chan=0; Chan<NChannels; Chan++) {
 		for (int i=0; i<S.ROI[Chip][Chan]; i++) {
-		  if (Boards[Brd]->ACalibTime == -1) Data[Count++] = Boards[Brd]->Data[Chip][Chan][i];
+		  if (Boards[Brd]->ACalib.Time == -1) Data[Count++] = Boards[Brd]->Data[Chip][Chan][i];
 		  else {
-		    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];
-			//Temp -= Boards[Brd]->SecondaryBaseline[Chip][Chan][i];
+		    Temp = (Boards[Brd]->Data[Chip][Chan][i] - Boards[Brd]->ACalib.Baseline[Chip][Chan][(i+S.TriggerCell[Chip])%NBins]);
+			Temp *= Boards[Brd]->ACalib.Gain[Chip][Chan][0]/Boards[Brd]->ACalib.Gain[Chip][Chan][(i+S.TriggerCell[Chip])%NBins];
+			//Temp -= Boards[Brd]->ACalib.Secondary[Chip][Chan][i];
 			Data[Count++] = (short) Temp;
 		  }
Index: fact/FADctrl/FAD.h
===================================================================
--- fact/FADctrl/FAD.h	(revision 10187)
+++ fact/FADctrl/FAD.h	(revision 10212)
@@ -20,4 +20,5 @@
 
 #include "FADBoard.h"
+#include "../drsdaq/RawDataCTX.h"
 
 const unsigned int PORT = 5000;
Index: fact/FADctrl/FADBoard.cc
===================================================================
--- fact/FADctrl/FADBoard.cc	(revision 10187)
+++ fact/FADctrl/FADBoard.cc	(revision 10212)
@@ -20,5 +20,5 @@
   Continue = true;
   CommOK = false;
-  ACalibTime = -1;
+  ACalib.Time = -1;
   Status.Update.tv_sec = -1;
   Port = ServerPort;
@@ -166,5 +166,5 @@
   case init:
 	// Invalidate current calibration
-	ACalibTime = -1;
+	ACalib.Time = -1;
 
 	// Save initial board status, set all ROIs to 1024 and set DAC values
@@ -203,5 +203,5 @@
 		for (unsigned int j=0; j<NChannels; j++) {
 		  for (unsigned int k=0; k<NBins; k++) {
-			Baseline[i][j][k] = Sum[i][j][k] / m->NumEventsRequested;
+			ACalib.Baseline[i][j][k] = Sum[i][j][k] / m->NumEventsRequested;
 		  }
 		}
@@ -237,5 +237,5 @@
 		for (unsigned int j=0; j<NChannels; j++) {
 		  for (unsigned int k=0; k<NBins; k++) {
-			Gain[i][j][k] = (Sum[i][j][k] / m->NumEventsRequested) - Baseline[i][j][k];
+			ACalib.Gain[i][j][k] = (Sum[i][j][k] / m->NumEventsRequested) - ACalib.Baseline[i][j][k];
 		  }
 		}
@@ -260,5 +260,5 @@
 	  for (unsigned int Chan=0; Chan<NChannels; Chan++) {
 		for (int i=0; i<Status.ROI[Chip][Chan]; i++) {
-		  Sum[Chip][Chan][i] = Data[Chip][Chan][i] - Baseline[Chip][Chan][(i-Status.TriggerCell[Chip]) % NBins];
+		  Sum[Chip][Chan][i] = Data[Chip][Chan][i] - ACalib.Baseline[Chip][Chan][(i-Status.TriggerCell[Chip]) % NBins];
 		}
 	  }
@@ -271,5 +271,5 @@
 		for (unsigned int j=0; j<NChannels; j++) {
 		  for (unsigned int k=0; k<NBins; k++) {
-			SecondaryBaseline[i][j][k] = Sum[i][j][k] / (double) m->NumEventsRequested;
+			ACalib.Secondary[i][j][k] = Sum[i][j][k] / (double) m->NumEventsRequested;
 		  }
 		}
@@ -290,7 +290,9 @@
 
 	  // Store calibration time and temperature
-	  ACalibTime = time(NULL);
-	  ACalibTemp = 0;
-	  for (unsigned int i=0; i<NTemp; i++) ACalibTemp += Status.Temp[i] / NTemp;
+	  ACalib.DNA = Status.DNA;
+	  ACalib.Frequency = Status.Frequency;
+	  ACalib.Time = time(NULL);
+	  ACalib.Temp = 0;
+	  for (unsigned int i=0; i<NTemp; i++) ACalib.Temp += Status.Temp[i] / NTemp;
 	  
 	  // Inform event thread that calibration is finished
@@ -415,9 +417,21 @@
 	  gettimeofday(&Status.Update, NULL);
 
-	  // Extract ID and type information
-	  Status.BoardID = ntohl(Header->board_id);
+	  // Extract board and trigger information
+	  Status.BoardID = ntohl(Header->board_id);	  
 	  Status.FirmwareRevision = ntohl(Header->version_no);
+	  Status.BoardTime = ntohl(Header->time);
+	  Status.EventCounter = ntohl(Header->fad_evt_counter);
 	  Status.TriggerID = ntohl(Header->trigger_id);
 	  Status.TriggerType = ntohs(Header->trigger_type);
+	  Status.TriggerCRC = ntohs(Header->trigger_crc);
+	  Status.DNA = Header->DNA;
+
+	  // Extract frequency related information
+	  Status.Frequency = ntohl(Header->REFCLK_frequency)/1.0e6;
+	  Status.PhaseShift = ntohs(Header->adc_clock_phase_shift);
+	  for (unsigned int i=0; i<NChips; i++) {
+		if ((Header->PLLLCK & (1<<i)) != 0) Status.Lock[i] = true;
+		else Status.Lock[i] = false;
+	  }
 
 	  // Extract temperatures (MSB indicates if temperature is positive or negative)
Index: fact/FADctrl/FADBoard.h
===================================================================
--- fact/FADctrl/FADBoard.h	(revision 10187)
+++ fact/FADctrl/FADBoard.h	(revision 10212)
@@ -38,11 +38,18 @@
 
 	struct BoardStatus {
-	  unsigned short BoardID;
-	  unsigned short FirmwareRevision;
-	  unsigned long TriggerID;
-	  unsigned char TriggerType;
-	  unsigned short TriggerCell[NChips];
-	  unsigned short ROI[NChips][NChannels];
-	  unsigned short DAC[NDAC];
+	  uint16_t BoardID;
+	  uint64_t DNA;
+	  uint16_t FirmwareRevision;
+	  uint32_t BoardTime;
+	  uint32_t EventCounter;
+	  uint32_t TriggerID;
+	  uint16_t TriggerType;
+	  uint16_t TriggerCRC;
+	  uint16_t TriggerCell[NChips];
+	  float Frequency;
+	  bool Lock[NChips];
+	  uint16_t PhaseShift;
+	  uint16_t ROI[NChips][NChannels];
+	  uint16_t DAC[NDAC];
 	  float Temp[NTemp];
 	  struct timeval Update;
@@ -51,10 +58,14 @@
 	short Data[NChips][NChannels][NBins];
 	long int Sum[NChips][NChannels][NBins];
-	short Baseline[NChips][NChannels][NBins];
-	double Gain[NChips][NChannels][NBins];
-	double SecondaryBaseline[NChips][NChannels][NBins];
-	float ACalibTemp;
-	time_t ACalibTime;
 
+	struct CalibData {
+	  uint64_t DNA;
+	  short Baseline[NChips][NChannels][NBins];
+	  double Gain[NChips][NChannels][NBins];
+	  double Secondary[NChips][NChannels][NBins];
+	  float Temp;
+	  float Frequency;
+	  time_t Time;
+	} ACalib;
 
 	void Send(const void *, size_t);
Index: fact/FADctrl/FADFormat.h
===================================================================
--- fact/FADctrl/FADFormat.h	(revision 10187)
+++ fact/FADctrl/FADFormat.h	(revision 10212)
@@ -2,5 +2,5 @@
 #define FADFORMAT_H_SEEN
 
-#include "../drsdaq/RawDataCTX.h"
+#include <stdint.h>
 
 //
@@ -30,13 +30,13 @@
 #define CMD_Write 0x0500 		// write to Config-RAM
 
-#define CMD_TRIGGERS_ON 0x1800	// enables the trigger line -- incoming triggers can now be accepted
-#define CMD_TRIGGERS_OFF 0x1900 // disables the trigger line -- no trigger will be accepted
+#define CMD_TRIGGERS_ON 0x1800	// enables the trigger line
+#define CMD_TRIGGERS_OFF 0x1900 // disables the trigger line
 
 //
 // Other definitions
 //
-#define MAX_ADDR 0xFF // highest address in Config-RAM
-#define BADDR_ROI 0x00 // Baseaddress ROI-Values
-#define BADDR_DAC 0x24 // Baseaddress DAC-Values
+#define MAX_ADDR 0xFF		// highest address in Config-RAM
+#define BADDR_ROI 0x00		// Baseaddress ROI-Values
+#define BADDR_DAC 0x24		// Baseaddress DAC-Values
 #define MAX_VAL 65535
 #define MAX_ROIVAL 1024
@@ -53,32 +53,33 @@
 //
 typedef struct {
-// ------------------------------
-uint16_t start_package_flag;
-uint16_t package_length;
-uint16_t version_no;
-uint16_t PLLLCK;
-// ------------------------------
-uint16_t trigger_crc;
-uint16_t trigger_type;
-uint32_t trigger_id;
-// ------------------------------
-uint32_t fad_evt_counter;
-uint32_t REFCLK_frequency;
-// ------------------------------
-uint16_t board_id;
-uint16_t adc_clock_phase_shift;
-uint16_t number_of_triggers_to_generate;
-uint16_t trigger_generator_prescaler;
-// ------------------------------
-uint8_t DNA[8]; // Xilinx DNA
-// ------------------------------
-uint32_t time;
-uint32_t fad_status;
-// ------------------------------
-int16_t drs_temperature[NTemp];
-// ------------------------------
-uint16_t dac[NDAC];
-// ------------------------------
+
+  uint16_t start_package_flag;
+  uint16_t package_length;
+  uint16_t version_no;
+  uint16_t PLLLCK;
+
+  uint16_t trigger_crc;
+  uint16_t trigger_type;
+  uint32_t trigger_id;
+
+  uint32_t fad_evt_counter;
+  uint32_t REFCLK_frequency;
+
+  uint16_t board_id;
+  uint16_t adc_clock_phase_shift;
+  uint16_t number_of_triggers_to_generate;
+  uint16_t trigger_generator_prescaler;
+
+  uint64_t DNA;
+
+  uint32_t time;
+  uint32_t fad_status;
+
+  int16_t drs_temperature[NTemp];
+
+  uint16_t dac[NDAC];
+
 } __attribute__((__packed__)) PEVNT_HEADER;
+
 typedef struct {
 uint16_t id;
Index: fact/FADctrl/History.txt
===================================================================
--- fact/FADctrl/History.txt	(revision 10187)
+++ fact/FADctrl/History.txt	(revision 10212)
@@ -16,2 +16,3 @@
 28/2/2011	Removed 'static' keywords in FADBoard::ReadLoop()
 1/3/2011	Board list can be passed via command line
+2/3/2011	Implemented new FAD data format
