Index: drsdaq/DAQReadout.cc
===================================================================
--- drsdaq/DAQReadout.cc	(revision 57)
+++ drsdaq/DAQReadout.cc	(revision 63)
@@ -59,5 +59,4 @@
 // -----------------------------------------------
 //
-// Note that constructor cannot report error and should not fail
  
 DAQReadout::DAQReadout(const char *Configfile) {
@@ -88,7 +87,6 @@
     ReadCard("MaxLogLines",        &fMaxLogLines,       'U', File);
     ReadCard("RawDataPath",         fRawDataPath,       's', File);
-    ReadCard("RotateWave",         &fRotateWave,        'I', File);
     ReadCard("FirstSample",        &fFirstSample,       'I', File);
-    ReadCard("LastSample",         &fLastSample,        'I', File);
+    ReadCard("Samples",     	   &fSamples,        	'U', File);
     ReadCard("MinDiskSpaceMB",     &fMinDiskSpaceMB,    'U', File);
     ReadCard("MaxFileSizeMB",      &fMaxFileSizeMB,     'I', File);
@@ -99,8 +97,8 @@
     fclose(File);
   }
-  if (fFirstSample < 0 || fFirstSample >= kNumberOfBins || fLastSample < 0 || fLastSample >= kNumberOfBins) {
+  if (fFirstSample < 0 || fFirstSample > kNumberOfBins || fSamples > kNumberOfBins) {
     PrintMessage("Warning: Sample range in configuration beyond limits, setting to full range\n");
-    fFirstSample = 0;
-    fLastSample = kNumberOfBins;
+    fFirstSample = kNumberOfBins;
+    fSamples = kNumberOfBins;
   }
   
@@ -128,6 +126,5 @@
 
   // Scan for DRS boards
-  if (drs->GetNumberOfBoards()==0)
-    PrintMessage("No DRS boards found - check VME crate and configuration file!\n");
+  if (drs->GetNumberOfBoards()==0) PrintMessage("No DRS boards found - check VME crate and configuration file!\n");
 
   for (int i=0; i<drs->GetNumberOfBoards(); i++) {
@@ -138,9 +135,10 @@
     LastBoard++;
     drs->GetBoard(i)->Init();
-    drs->GetBoard(i)->SetRotation(fRotateWave);
+    drs->GetBoard(i)->SetRotation(false);
     DRSFreq[i] = 0;
   }
   BStruct  = new BoardStructure [NumBoards == 0 ? 1:drs->GetNumberOfBoards()];
   WaveForm = new short [NumBoards == 0 ? 1:NumBoards][kNumberOfChips][kNumberOfChannels][kNumberOfBins];
+  TriggerCell = new int [NumBoards == 0 ? 1:NumBoards][kNumberOfChips] ();  // Zero initialised
   
   // Create instance of HV feedback (must be called after CMC board detection)
@@ -162,5 +160,5 @@
   delete drs;	      delete HVFB;
   delete[] DRSFreq;   delete[] BStruct;
-  delete[] WaveForm;
+  delete[] WaveForm;  delete[] TriggerCell;
   
   PrintMessage(MsgToLog,"********** Logging ended **********\n\n");
@@ -219,8 +217,9 @@
 void DAQReadout::cmd_config() {
   PrintMessage("LogFile: %s\tMaxLogLines: %u\tRawDataPath: %s\n"
-      	       "RotateWave: %d\t\tFirstSample: %d\t\tLastSample: %d\n"
+      	       "FirstSample: %d\tSamples: %u\n"
      	       "MinDiskSpaceMB: %u\tMaxFileSizeMB: %d\tCCPort: %d\n"
-      	       "FirstVMESlot: %d\t\tLastVMESlot: %d\t\tHVFeedbackConfig: %s\n",
-    fLogFile,fMaxLogLines,fRawDataPath,fRotateWave,fFirstSample,fLastSample,fMinDiskSpaceMB,
+      	       "FirstVMESlot: %d\t\tLastVMESlot: %d\n"
+	       "HVFeedbackConfig: %s\n",
+    fLogFile,fMaxLogLines,fRawDataPath,fFirstSample,fSamples,fMinDiskSpaceMB,
     fMaxFileSizeMB,fCCPort,fFirstVMESlot,fLastVMESlot,fHVFeedbackConfig);
 }
@@ -664,7 +663,9 @@
   for (int i=FirstBoard; i<=LastBoard; i++) {
     (drs->GetBoard(i))->TransferWaves(kNumberOfChannels*kNumberOfChips); 
-    for (int ch=0; ch<kNumberOfChannels; ch++) {
-       (drs->GetBoard(i))->GetWave(0, ch, WaveForm[i][0][ch], true); // Chip #1
-       (drs->GetBoard(i))->GetWave(1, ch, WaveForm[i][1][ch], true); // Chip #2
+    for (int j=0; j<kNumberOfChannels; j++) {
+       drs->GetBoard(i)->GetWave(0, j, WaveForm[i][0][j], true); // Chip #1
+       TriggerCell[i][0] = drs->GetBoard(i)->GetTriggerCell((unsigned int) 0);
+       drs->GetBoard(i)->GetWave(1, j, WaveForm[i][1][j], true); // Chip #2
+       TriggerCell[i][1] = drs->GetBoard(i)->GetTriggerCell((unsigned int) 1);
     }
   }
@@ -926,5 +927,5 @@
 
   RHeader->Offset  = fFirstSample;
-  RHeader->Samples = fLastSample - fFirstSample + 1;
+  RHeader->Samples = fSamples;
 
   if(write(Rawfile, RHeader, sizeof(RunHeader)) != sizeof(RunHeader)) {
@@ -953,5 +954,5 @@
 }
 
-// Update the run header before closing file
+// Update run header before closing file
 bool DAQReadout::UpdateRunHeader(unsigned int Events, bool Error) {
 
@@ -988,5 +989,6 @@
   EHeader->Second = Time.tv_sec;
   EHeader->Microsecond = Time.tv_usec;
-  EHeader->EventSize = sizeof(short)*RHeader->NBoards*RHeader->NChips*RHeader->NChannels*RHeader->Samples;
+  EHeader->EventSize = sizeof(short)*RHeader->NBoards*RHeader->NChips*RHeader->NChannels*RHeader->Samples +
+    	    	       sizeof(int)*RHeader->NBoards*RHeader->NChips;
 
   if(write(Rawfile, EHeader, sizeof(EventHeader)) != sizeof(EventHeader)) {
@@ -994,4 +996,48 @@
     return false;
   }
+  return true;
+}
+
+// Write event data (It is required that at least three chunks can be written with writev(), therefore
+// IOV_MAX>=3 is checked at startup
+bool DAQReadout::WriteEventData() {
+
+  unsigned int Start, Count = 0;
+  ssize_t WriteResult, Size = 0;
+  struct iovec DataPart[IOV_MAX];
+
+  // First chunk: trigger cells
+  DataPart[Count].iov_base = TriggerCell + FirstBoard*kNumberOfChips;
+  DataPart[Count++].iov_len = RHeader->NBoards * kNumberOfChips * sizeof(int);
+  Size += DataPart[Count-1].iov_len;
+
+  // Remaining chunks: ADC data (two chucks per channel if wrap around of pipeline occurred)
+  for (int i=FirstBoard; (i<=LastBoard + (NumBoards==0)); i++) {
+    for (unsigned int k=0; k<RHeader->NChips; k++) {
+      Start = (TriggerCell[i][k]-fFirstSample+kNumberOfBins) % kNumberOfBins;  // Start bin for this chip
+      for (unsigned int l=0; l<RHeader->NChannels; l++) {
+	DataPart[Count].iov_base = &WaveForm[i][k][l][Start];
+	DataPart[Count++].iov_len = (Start+fSamples<kNumberOfBins ? fSamples:(kNumberOfBins-Start)) * sizeof(short);
+	Size += DataPart[Count-1].iov_len;
+	// In case second part of waveform still missing, write now
+	if(DataPart[Count-1].iov_len < fSamples * sizeof(short)) {
+    	  DataPart[Count].iov_base = &WaveForm[i][k][l][0];
+	  DataPart[Count++].iov_len = (fSamples-(kNumberOfBins-Start)) * sizeof(short);
+    	  Size += DataPart[Count-1].iov_len;
+	}
+
+	// Write to disk if either maximum size of DataPart[] array or last loop interation is reached 
+	// Possibly 2 chunks are entered in array in the previous lines of code, therefore IOV_MAX-1
+	if (Count>=IOV_MAX-1 || (l==(RHeader->NChannels-1) && k==(RHeader->NChips-1) && i==(LastBoard+(NumBoards==0)))) {
+	  if ((WriteResult=writev(Rawfile, DataPart, Count)) != (int) Size) {
+            if (WriteResult==-1) PrintMessage("Error: Could not write event data, terminating run (%s)\n", strerror(errno));
+            else PrintMessage("Error: Could only write %u out of %u bytes of event data, terminating run\n", WriteResult,Count*DataPart[0].iov_len);
+	    return false;
+	  }
+	  Count = 0;   Size = 0;
+	}
+      } // Channels
+    } // Chips
+  } // Boards
   return true;
 }
@@ -1143,10 +1189,7 @@
 
   struct timeval StartTime, StopTime;
-  int Count;
   unsigned int EventsInFile;
   unsigned long long RunSize = 0;
   bool WriteError = false;
-  struct iovec DataPart[IOV_MAX];
-  ssize_t WriteResult;
   off_t FileSize;
 
@@ -1155,6 +1198,6 @@
   m->HVFB->ClearAverages();    
   gettimeofday(&StartTime, NULL);
-
   m->PrintMessage("\rStarting run #%d (%s) on \"%s\" with %u event(s)\n",m->RunNumber,daq_runtype_str[m->daq_runtype],m->RHeader->Description,m->NumEventsRequested);
+
   do {
     // Check if enough disk space is left
@@ -1169,4 +1212,5 @@
     EventsInFile = 0;
     FileSize = 0;
+
     WriteError |= !m->WriteRunHeader();
     
@@ -1190,33 +1234,16 @@
       else {
 	double Period = ((double) rand())/RAND_MAX*20;
-	for (long int i=0; i<(m->NumBoards>0 ?  m->NumBoards : 1)*kNumberOfChips*kNumberOfChannels*kNumberOfBins; i++)
+	for (long unsigned int i=0; i<m->RHeader->NBoards*kNumberOfChips*kNumberOfChannels*kNumberOfBins; i++)
 	  *((short *) m->WaveForm+i) = (short) (sin(i/Period)*1000);
       }
 
-      // Write data to disk (using writev() for performance reason)
-      Count  = 0;
-      for (int i=m->FirstBoard; (i<=m->LastBoard + (m->NumBoards==0)) && !WriteError; i++) {
-        for (unsigned int k=0; k<m->RHeader->NChips*m->RHeader->NChannels; k++) {
-    	  DataPart[Count].iov_base = &m->WaveForm[i][k/m->RHeader->NChannels][k%m->RHeader->NChannels][m->RHeader->Offset];
-    	  DataPart[Count++].iov_len = m->RHeader->Samples * sizeof(short);
-	
-	  // Write to disk if either maximum size of DataPart[] array or last loop interation is reached 
-	  if (Count==IOV_MAX || (k==(m->RHeader->NChips*m->RHeader->NChannels-1) && i==(m->LastBoard+(m->NumBoards==0)))) {
-	    if ((WriteResult=writev(m->Rawfile, DataPart, Count)) != (int) (Count*DataPart[0].iov_len)) {
-              if (WriteResult==-1) m->PrintMessage("Error: Could not write event data, terminating run (%s)\n", strerror(errno));
-              else m->PrintMessage("Error: Could only write %u out of %u bytes of event data, terminating run\n", WriteResult,Count*DataPart[0].iov_len);
-	      WriteError = true;
-	      break;
-	    }
-	    Count = 0;
-	  }
-        }
-      }
-
-      // Update file size
+      // Write data to disk and update file size
+      WriteError |= !m->WriteEventData();
+
       if((FileSize = lseek(m->Rawfile, 0, SEEK_CUR)) == -1) {
     	m->PrintMessage("Error: Could not determine file size, terminating run (%s)\n", strerror(errno));
 	WriteError = true;
       }
+
       // Call feedback to process event
       m->HVFB->ProcessEvent();
@@ -1232,4 +1259,5 @@
   } while(m->NumEvents<m->NumEventsRequested && !m->Stop && !WriteError);
 
+  // Print run summary to slow data file and to screen
   m->StopDRS();
   if(!WriteError) {
@@ -1239,4 +1267,6 @@
   }
   else m->PrintMessage("\rRun #%d (%s) aborted due to error after %d events\n",m->RunNumber,daq_runtype_str[m->daq_runtype],m->NumEvents);
+
+  // Print run statistics
   if (m->NumEvents>0 && !WriteError) {
     gettimeofday(&StopTime, NULL);
@@ -1245,4 +1275,5 @@
     m->PrintMessage("Run size %llu MByte, data rate %.1f MByte/s.\n", RunSize/1024/1024, RunSize/1024.0/1024/RunTime);
   }
+  
   m->daq_state = stopped;
 }
Index: drsdaq/DAQReadout.h
===================================================================
--- drsdaq/DAQReadout.h	(revision 57)
+++ drsdaq/DAQReadout.h	(revision 63)
@@ -44,4 +44,6 @@
     
     short (*WaveForm)[kNumberOfChips][kNumberOfChannels][kNumberOfBins];
+    int (*TriggerCell)[kNumberOfChips];
+
     pthread_mutex_t control_mutex;
     int Rawfile;
@@ -55,7 +57,6 @@
     int fMinDiskSpaceMB;   // Minimum required disk space in MBytes
     int fMaxFileSizeMB;    // Maximum File size in Bytes 
-    unsigned int fFirstSample;
-    unsigned int fLastSample;
-    short fRotateWave;
+    int fFirstSample;
+    unsigned int fSamples;
     int fCCPort;
     int fLastVMESlot;
@@ -128,4 +129,5 @@
     bool UpdateRunHeader(unsigned int, bool);
     bool WriteEventHeader();
+    bool WriteEventData();
 };
 
Index: drsdaq/History.txt
===================================================================
--- drsdaq/History.txt	(revision 57)
+++ drsdaq/History.txt	(revision 63)
@@ -34,2 +34,8 @@
     	    safe for buffer overflow. RawDataCTX class take the possibility of
 	    varying event data size into account.
+12/6/2009   Trigger cells (determined using DRS class GetTriggerCell()) are
+    	    stored as array of integers in event data. RawDataCTX class pointer
+	    'Data' changed from short* to char*.
+16/6/2009   Data is not rotated by copying in memory, but by saving to disk in
+    	    correct order using writev() (10% gain in rate)
+	    
Index: drsdaq/Makefile
===================================================================
--- drsdaq/Makefile	(revision 57)
+++ drsdaq/Makefile	(revision 63)
@@ -25,9 +25,9 @@
 endif
 
-CPPFLAGS = -DREVISION='"$(REVISION)"' -Wl,-rpath,VME/atlas/lib -O3 -Wall $(VMECTRL)
+CPPFLAGS = -DREVISION='"$(REVISION)"' -O3 -Wall $(VMECTRL)
 LIBS = -lstdc++ -lz -lpthread -lutil -lfl -lreadline -ltermcap $(VMELIB)
 
 drsdaq: $(OBJECTS)
-	$(CC) $(CPPFLAGS) -o $@ $(OBJECTS) $(LIBS)
+	$(CC) $(CPPFLAGS) -Wl,-rpath,VME/atlas/lib -o $@ $(OBJECTS) $(LIBS)
 
 clean:
Index: drsdaq/RawDataCTX.cc
===================================================================
--- drsdaq/RawDataCTX.cc	(revision 57)
+++ drsdaq/RawDataCTX.cc	(revision 63)
@@ -29,6 +29,8 @@
 // *** Open raw data file
 CTX_ErrCode RawDataCTX::OpenDataFile(char *Filename, FILE *fptr) {
-    
+
+  // Close file if currently open    
   if(FileOpen) CloseDataFile();
+
   // Open file
   if ((Rawfile = fopen(Filename, "r")) == NULL) {
@@ -36,4 +38,5 @@
     return CTX_FOPEN;
   }
+
   // Read run header
   if (fread(RHeader, sizeof(RunHeader), 1, Rawfile) != 1) {
@@ -42,4 +45,5 @@
     return CTX_RHEADER;  
   }
+
   // Check magic number of run header
   if (RHeader->MagicNum!=MAGICNUM_OPEN && RHeader->MagicNum!=MAGICNUM_CLOSED && RHeader->MagicNum!=MAGICNUM_ERROR) {
@@ -48,4 +52,5 @@
     return CTX_RHEADER;  
   }
+
   // Check if version of this software is not older than raw data format
   if (RHeader->DataFormat > DATA_FORMAT) {
@@ -54,4 +59,5 @@
     return CTX_VERSION;  
   }  
+
   // Check if allocated headers are long enough
   if (RHeader->RunHeaderSize>sizeof(RunHeader) || RHeader->BoardStructureSize>sizeof(BoardStructure) || RHeader->EventHeaderSize>sizeof(EventHeader)) {
@@ -71,6 +77,7 @@
     }
   }
-  // Allocate memory for event data
-  Data = new short[RHeader->NBoards*RHeader->NChips*RHeader->NChannels*RHeader->Samples];
+
+  // Initialize variables
+  Data = NULL;
   FileOpen = true;
   
@@ -110,4 +117,5 @@
     }     
   }
+
   return CTX_OK;
 }
@@ -123,7 +131,6 @@
   }
   
-  delete[] BStruct;
-  delete[] Data;
-  
+  delete[] BStruct; 	delete[] Data;
+ 
   FileOpen = false;
   return CTX_OK;
@@ -159,4 +166,10 @@
   }
 
+  // Allocate memory for event data (enlarge if necessary)
+  if(Data==NULL || (sizeof(Data) < EHeader->EventSize)) {
+    delete[] Data;
+    Data = new char[EHeader->EventSize];
+  }
+
   // Read event data
   if(fread(Data, 1, EHeader->EventSize, Rawfile) != EHeader->EventSize) {
Index: drsdaq/RawDataCTX.h
===================================================================
--- drsdaq/RawDataCTX.h	(revision 57)
+++ drsdaq/RawDataCTX.h	(revision 63)
@@ -98,6 +98,6 @@
     EventHeader *EHeader;
     BoardStructure *BStruct;
-    short *Data; 
-
+    char *Data; 
+    
     RawDataCTX(bool = false);
     ~RawDataCTX();
Index: drsdaq/drsdaq.cpp
===================================================================
--- drsdaq/drsdaq.cpp	(revision 57)
+++ drsdaq/drsdaq.cpp	(revision 63)
@@ -43,4 +43,10 @@
   int LockDescriptor;
  
+ // writev() in DAQ thread needs to be able to write at least 3 chunks
+ if(IOV_MAX < 3) {
+   printf("Fatal error: IOV_MAX is less than 3, cannot use writev() to write event data.\n");
+   exit(EXIT_FAILURE);
+ }
+   
   // Interpret command line (do before lockfile creation in case of exit())
   if((argc==3 && strcmp(argv[1],"-c")!=0) || argc==2) {
