Index: fact/FADctrl/FAD.cc
===================================================================
--- fact/FADctrl/FAD.cc	(revision 10642)
+++ fact/FADctrl/FAD.cc	(revision 10757)
@@ -20,5 +20,5 @@
 			  const char *Help;
   } CommandList[] = 
-  {{"board", &FAD::cmd_board, true, 1, "[+|-]<range>" ,"Activate or deactivate board(s)"},
+  {{"board", &FAD::cmd_board, false, 1, "[+|-]<range>" ,"Activate or deactivate board(s)"},
    {"status", &FAD::cmd_status, false, 0, "[range]", "Show board status information"},
    {"domino", &FAD::cmd_domino, true, 1, "<on|off>", "Switch Domino wave"},
@@ -28,5 +28,5 @@
    {"sclk", &FAD::cmd_sclk, true, 1, "<on|off>", "Set SCLK"},
    {"trigger", &FAD::cmd_trigger, false, 0, "[n|cont [rate]|stop|enable|disable]", "Issue software triggers"},
-   {"reset_trigger", &FAD::cmd_reset_trigger, true, 0, "", "Reset internal trigger counter"},
+   {"reset", &FAD::cmd_reset, true, 0, "", "Reset internal trigger counter"},
    {"runnumber", &FAD::cmd_runnumber, true, 1, "<n>", "Set runnumber"},
    {"roi", &FAD::cmd_roi, true, 2, "<channel range> <value>", "Set region-of-interest to value"},
@@ -199,5 +199,5 @@
 //
 
-void FAD::cmd_reset_trigger() {
+void FAD::cmd_reset() {
 
   for (unsigned int i=0; i<Boards.size(); i++) Boards[i]->Send(CMD_RESET_TRIGGER_ID);
@@ -379,8 +379,13 @@
 	Buffer[2*i+1] = htons(Value);
   }
-  
-  // Send command buffer
+
+  // Disable triggers for all boards and wait (workaround for firmware bug)  
+  for (unsigned int i=0; i<Boards.size(); i++) Boards[i]->Send(CMD_TRIGGERS_OFF);
+  usleep(500000);
+
+  // Send command buffer and enable triggers again
   for (unsigned int i=0; i<Boards.size(); i++) {
 	Boards[i]->Send(Buffer, sizeof(Buffer));
+	Boards[i]->Send(CMD_TRIGGERS_ON);
   }
 } 
@@ -542,4 +547,5 @@
 	FILE *File;
 	struct FADBoard::CalibData Data;
+	bool Found = false;
 
     // Open file
@@ -553,6 +559,9 @@
 	    PrintMessage("Found calibration for board %d - %s", i, ctime(&Data.Time));
 	    Boards[i]->ACalib = Data;
+		Found = true;
 	  }
 	}
+	if (!Found) PrintMessage("Did not find calibration data for any board\n");
+
 	//Close file
 	if (fclose(File) != 0) PrintMessage("Could not close file '%s'\n", Parameter[1].c_str());
@@ -596,11 +605,15 @@
 
 	// Print list of active boards
-	PrintMessage("Active are %d boards(s)   ", Count);
+	PrintMessage("Active (%d)\t", Count);
 	for (unsigned int i=0; i<Boards.size(); i++) {
 	  if (Boards[i]->Active) PrintMessage(" %d%s", i, Boards[i]->CommOK ? "":"!");
 	}
+	PrintMessage("\nInactive (%d)  ", Boards.size()-Count);
+	for (unsigned int i=0; i<Boards.size(); i++) {
+	  if (!Boards[i]->Active) PrintMessage(" %d%s", i, Boards[i]->CommOK ? "":"!");
+	}
 	PrintMessage("\n");
 
-	// Current mode
+	// Print current mode
 	if (Mode == idle) PrintMessage("Current mode is IDLE\n");
 	else if (Mode == acalib) PrintMessage("Current mode is ACALIB (3x%d events, slowest board %d has %d events)\n", NumEventsRequested, SlowestBoard, MinCount);
@@ -945,5 +958,5 @@
 	  // Fill M0 BoardStructure		
 	  S = Boards[Brd]->GetStatus();
-	  BStruct[Brd]->SerialNo = S.BoardID;
+	  BStruct[Brd]->SerialNo = (U32) S.DNA;
 	  BStruct[Brd]->NomFreq = S.Frequency;
 	  BStruct[Brd]->BoardTemp = 0;        
Index: fact/FADctrl/FAD.h
===================================================================
--- fact/FADctrl/FAD.h	(revision 10642)
+++ fact/FADctrl/FAD.h	(revision 10757)
@@ -69,7 +69,6 @@
 	void cmd_board();		void cmd_status();
 	void cmd_acalib();		void cmd_serial();
-	void cmd_trigger(); 
-	void cmd_runnumber();	void cmd_reset_trigger();
-	void cmd_socketmode();
+	void cmd_trigger();		void cmd_socketmode();
+	void cmd_runnumber();	void cmd_reset();
 	void cmd_srclk();		void cmd_sclk();
 	void cmd_dwrite();		void cmd_domino();
Index: fact/FADctrl/FADBoard.cc
===================================================================
--- fact/FADctrl/FADBoard.cc	(revision 10642)
+++ fact/FADctrl/FADBoard.cc	(revision 10757)
@@ -33,14 +33,17 @@
   pthread_mutexattr_t Attr;
 
+  if ((Ret = pthread_mutexattr_init(&Attr)) != 0) {
+    m->Message(m->ERROR, "pthread_mutex_init() failed in FADBoard constructor (%s)", strerror(Ret));
+  }
   if ((Ret = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_ERRORCHECK)) != 0) {
-    m->Message(m->ERROR, "pthread_mutex_settype() failed (%s)", strerror(Ret));
+    m->Message(m->ERROR, "pthread_mutex_settype() failed in FADBoard constructor (%s)", strerror(Ret));
   }
   if ((Ret = pthread_mutex_init(&Mutex, &Attr)) != 0) {
-    m->Message(m->FATAL, "pthread_mutex_init() failed (%s)", strerror(Ret));
+    m->Message(m->FATAL, "pthread_mutex_init() failed in FADBoard constructor (%s)", strerror(Ret));
   }
 
   // Initialise condition variable for synchronization
   if ((Ret = pthread_cond_init(&CondVar, NULL)) != 0) {
-    m->Message(m->FATAL, "pthread_cond_init() failed (%s)", strerror(Ret));
+    m->Message(m->FATAL, "pthread_cond_init() failed in FADBoard constructor (%s)", strerror(Ret));
   }
 
@@ -63,5 +66,5 @@
   SetStatus("Trying to connect...");
 
-  if ((Ret = pthread_create(&Thread, NULL, (void * (*)(void *)) LaunchThread,(void *) this)) != 0) {
+  if ((Ret = pthread_create(&Thread, NULL, (void * (*)(void *)) LaunchThread, (void *) this)) != 0) {
     m->Message(m->FATAL, "pthread_create() failed in FADBoard() (%s)", strerror(Ret));
   }
@@ -177,6 +180,9 @@
 	Count = 0;
 
-	// Save initial board status, set all ROIs to 1024 and set DAC values
+	// Save initial board status, set all ROIs to 1024 and set DAC values (no triggers while setting ROI)
 	InitialStatus = GetStatus();
+
+	Send(CMD_TRIGGERS_OFF);
+	usleep(500000);
 
 	for (unsigned int i=0; i<NChips*NChannels; i++) {
@@ -191,7 +197,10 @@
 	Send(DACCmd, sizeof(DACCmd));
 
+	Send(CMD_TRIGGERS_ON);
+
 	// Clear sum vector and set state to accumulate
 	memset(Sum, 0, sizeof(Sum));
 	State = baseline;
+	SetStatus("Starting calilbration");
 	break;
 
@@ -319,4 +328,5 @@
 	}
 
+	SetStatus("Finished calibration");
 	State = cleanup;
 	break;
@@ -325,4 +335,7 @@
   case cleanup:
     // ROI values
+	Send(CMD_TRIGGERS_OFF);
+	usleep(100000);
+
 	ROICmd.clear();
 	for (unsigned int i=0; i<NChips*NChannels; i++) {
@@ -331,4 +344,6 @@
 	}
 	Send(&ROICmd[0], ROICmd.size()*sizeof(unsigned short));
+
+	Send(CMD_TRIGGERS_ON);
 
 	// DAC values
@@ -421,5 +436,5 @@
 	// If not active, discard incoming data
 	if (!Active) continue;
-	
+
 	// Advance write pointer
 	Pos += Result;
@@ -461,6 +476,10 @@
 	  Lock();
 	  while (!Continue) {
-		if ((Ret = pthread_cond_wait(&CondVar, &Mutex)) != 0) {
-		  m->Message(m->ERROR, "pthread_cond_wait() failed (%s)", strerror(Ret));
+		struct timespec Wakeup;
+		Wakeup.tv_sec = time(NULL)+5;
+		Wakeup.tv_nsec = 0;
+		if ((Ret = pthread_cond_timedwait(&CondVar, &Mutex, &Wakeup)) != 0) {
+		  if (Ret == ETIMEDOUT) printf("Board %s timed out (5 s) waiting for condition\n", Name);
+		  else m->Message(m->ERROR, "pthread_cond_wait() failed (%s)", strerror(Ret));
 		}
 	  }
@@ -580,9 +599,11 @@
 
 //
-// Launch read thread inside class
+// Install cleanup handler and launch read thread inside class
 //
 void FADBoard::LaunchThread(class FADBoard *m) {
 
+  pthread_cleanup_push((void (*)(void *)) FADBoard::ThreadCleanup, (void *) m);
   m->ReadLoop();
+  pthread_cleanup_pop(0);
 }
 
@@ -631,4 +652,14 @@
 }
 
+// Ensure that mutex is unlocked when before cancelling thread
+void FADBoard::ThreadCleanup(class FADBoard *This) {
+
+  int Ret;
+
+  if ((Ret = pthread_mutex_trylock(&This->Mutex)) != 0) {
+	if (Ret != EBUSY) This->m->Message(This->m->FATAL, "pthread_mutex_trylock() failed in FADBoard::ThreadCleanup (%s)", strerror(Ret));
+  }
+  This->Unlock();
+}
 
 //
Index: fact/FADctrl/FADBoard.h
===================================================================
--- fact/FADctrl/FADBoard.h	(revision 10642)
+++ fact/FADctrl/FADBoard.h	(revision 10757)
@@ -33,4 +33,5 @@
 	void ReadLoop();
 	static void LaunchThread(class FADBoard *);
+	static void ThreadCleanup(class FADBoard *);
 	void threadHandler();
 	void SetStatus(const char *, ...);
Index: fact/FADctrl/History.txt
===================================================================
--- fact/FADctrl/History.txt	(revision 10642)
+++ fact/FADctrl/History.txt	(revision 10757)
@@ -25,2 +25,6 @@
 4/5/2011	Removed 'daqmode' (had no function). Added 'reset_trigger' and 'runnumber' commands.
 			Event format adapted (ADC data not sent in network byte order anymore).
+20/5/2011	Missing pthread_mutexattr_init() in FADBoard constructor caused spurious errors when
+			locking mutex
+			Added cleanup handler to thread in FADBoard class to ensure mutex is unlocked when thread
+			cancelled
