unit Convert;
{ ==========================================================================
  WinWCP - File importing module (c) J Dempster, 1996-97, All Rights Reserved
  7/6/97 ... AppendWCPFile added
  10/6/97 ... WCPTopCLAMP added
  24/8/97 ... ImportFromDataFile and CFSToWCP added
  27/5/99 ... Updated to support ABF V1.5
  ========================================================================== }
interface

uses global,fileio,SysUtils,shared,Dialogs,Messages,forms,controls, maths,Import;

type
    TpClampV5 = record
	par : Array[0..79] of single ;
	Comment : Array[1..77] of char ;
        Labels : Array[1..80] of char ;
        Reserved : Array[1..35] of char ;
        Pulse : Array[1..64] of char ;
	ParExt : Array[0..15] of single ;
	ADCOffset : Array[0..15] of single ;
	ADCGain : Array[0..15] of single ;
        ADCAmplification : Array[0..15] of single ;
	ADCShift : Array[0..15] of single ;
	Units : Array[0..15,1..8] of char ;
        end ;

    TABF = record
         FileType : Array[1..4] of char ;
         FileVersionNumber : single ;
	 OperationMode : Integer ;
	 ActualAcqLength : LongInt ;
	 NumPointsIgnored : integer ;
	 ActualEpisodes : LongInt ;
	 FileStartDate : LongInt ;
	 FileStartTime : LongInt ;
	 StopwatchTime : LongInt ;
	 HeaderVersionNumber : single ;
	 nFileType : Integer ;
	 MSBinFormat : Integer ;
	 DataSectionPtr : LongInt ;
	 TagSectionPtr : LongInt ;
	 NumTagEntries : LongInt ;
	 LongDescriptionPtr : LongInt ;
	 LongDescriptionLines : LongInt ;
	 DACFilePtr : LongInt ;
	 DACFileNumEpisodes : LongInt ;
	 Unused : Array[1..4] of char ;

	 DeltaArrayPtr : LongInt ;
	 NumDeltas : LongInt ;
	 NoteBookPtr : LongInt ;
	 NotebookManEntries : LongInt ;
	 NotebookAutoEntries : LongInt ;
	 SynchArrayPtr : LongInt ;
	 SynchArraySize : LongInt ;
         DataFormat : Integer ;
	 Unused100 : Array[1..18] of char ;

	 ADCNumChannels : Integer ;
	 ADCSampleInterval : single ;
	 ADCSecondSampleInterval : single ;
	 SynchTimeUnit : single ;
	 SecondsPerRun : single ;
	 NumSamplesPerEpisode : LongInt ;
	 PreTriggerSamples : LongInt ;
	 EpisodesPerRun : LongInt ;
	 RunsPerTrial : LongInt ;
	 NumberOfTrials : LongInt ;
	 AveragingMode  : Integer ;
	 UndoRunCount : Integer ;
	 FirstEpisodeInRun : Integer ;
	 TriggerThreshold : single ;
	 TriggerSource : Integer ;
	 TriggerAction : Integer ;
	 TriggerPolarity : Integer ;
	 ScopeOutputInterval : single ;
	 EpisodeStartToStart : single ;
	 RunStartToStart : single ;
	 TrialStartToStart : single ;
	 AverageCount : LongInt ;
	 Unused194 : Array[1..6] of char ;

	 DrawingStrategy : Integer ;
	 TiledDisplay : Integer ;
	 nEraseStrategy : Integer ;
	 DataDisplayMode : Integer ;
	 DisplayAverageUpdate : LongInt ;
	 ChannelStatsStrategy : Integer ;
	 CalculationPeriod : LongInt ;
	 SamplesPerTrace : LongInt ;
	 StartDisplayNum : LongInt ;
	 FinishDisplayNum : LongInt ;
	 MultiColor : Integer ;
	 ShowPNRawData : Integer ;
	 Unused234 : Array[1..10] of char ;

	 ADCRange : single ;
	 DACRange : single ;
	 ADCResolution : LongInt ;
	 DACResolution : LongInt ;
	 ExperimentType : Integer ;
	 AutosampleEnable : Integer ;
	 AutosampleADCNum : Integer ;
	 AutosampleInstrument : Integer ;
	 AutosampleAdditGain : single ;
	 AutosampleFilter : single ;
	 AutosampleMembraneCap : single ;
	 ManualInfoStrategy : Integer ;
	 CellID1 : single ;
	 CellID2 : single ;
	 CellID3 : single ;
	 CreatorInfo : Array[1..16] of char ;
	 FileComment : Array[1..56] of char ;
	 Unused366 : Array[1..12] of char ;

	 ADCPtoLChannelMap : Array[0..15] of Integer ;
	 ADCSamplingSeq : Array[0..15] of Integer ;
	 ADCChannelName : Array[0..15,1..10] of char ;
	 ADCUnits: Array[0..15,1..8] of char ;
	 ProgrammableGain : Array[0..15] of  single ;
	 DisplayAmplification : Array[0..15] of  single ;
	 DisplayOffset : Array[0..15] of  single ;
	 InstrumentScaleFactor : Array[0..15] of  single ;
	 InstrumentOffset : Array[0..15] of  single ;
	 SignalGain : Array[0..15] of  single ;
	 SignalOffset : Array[0..15] of  single ;
	 SignalLowPassFilter : Array[0..15] of  single ;
	 SignalHighPassFilter : Array[0..15] of  single ;

         DACChannelName : Array[0..3,1..10] of char ;
         DACChannelUnits : Array[0..3,1..8] of char ;
         DACScaleFactor : Array[0..3] of single ;
         DACHoldingLevel : Array[0..3] of single ;
         SignalType : Integer ;
         Unused1412 : Array[1..10] of char ;

         OutEnable : Integer ;
         SampleNumberOUT1 : Integer ;
         SampleNumberOUT2 : Integer ;
         FirstEpisodeOUT : Integer ;
         LastEpisodeOut : Integer ;
         PulseSamplesOUT1 : Integer ;
         PulseSamplesOUT2 : Integer ;

         DigitalEnable : Integer ;
         WaveformSource : Integer ;
         ActiveDACChannel : Integer ;
         InterEpisodeLevel : Integer ;
         EpochType : Array[0..9] of Integer ;
         EpochInitLevel : Array[0..9] of single ;
         EpochLevelInc : Array[0..9] of single ;
         EpochInitDuration : Array[0..9] of Integer ;
         EpochDurationInc : Array[0..9] of Integer ;
         DigitalHolding : Integer ;
         DigitalInterEpisode : Integer ;
         DigitalValue : Array[0..9] of Integer ;
         Unused1608 : Array[1..12] of char ;

         DACFileStatus : single ;
         DACFileOffset : single ;
         DACFileAutoScale : Integer ;
         DACFileEpisodeNum : Integer ;
         DACFileADCNum : Integer ;
         DACFileName : Array[1..12] of char ;
         DACFilePath : Array[1..60] of char ;
         Unused1706 : Array[1..12] of char ;

         ConditEnable : Integer ;
         ConditChannel : Integer ;
         ConditNumPulses : LongInt ;
         BaselineDuration : single ;
         BaselineLevel : single ;
         StepDuration : single ;
         StepLevel : single ;
         PostTrainPeriod : single ;
         PostTrainLevel : single ;
         Unused1750 : array[1..12] of char ;

         ParamToVary : Integer ;
         ParamValueList : Array[1..80] of char ;

         AutoPeakEnable : Integer ;
         AutoPeakPolarity : Integer ;
         AutoPeakADCNum : Integer ;
         AutoPeakSearchMode : Integer ;
         AutoPeakStart : LongInt ;
         AutoPeakEnd : LongInt ;
         AutoPeakSmoothing : Integer ;
         AutoPeakBaseline : Integer ;
         AutoPeakAverage : Integer ;
         Unused1866 : array[1..14] of char ;

         ArithmeticEnable : Integer ;
         ArithmeticUpperLimit : single ;
         ArithmeticLowerLimit : single ;
         ArithmeticADCNumA : Integer ;
         ArithmeticADCNumB : Integer ;
         ArithmeticK1 : single ;
         ArithmeticK2  : single ;
         ArithmeticK3 : single ;
         ArithmeticK4 : single ;
         ArithmeticOperator : Array[1..2] of char ;
         ArithmeticUnits : Array[1..8] of char ;
         ArithmeticK5 : single ;
         ArithmeticK6 : single ;
         ArithmeticExpression : Integer ;
         Unused1930 : array[1..2] of char ;

         PNEnable : Integer ;
         PNPosition : Integer ;
         PNPolarity : Integer ;
         PNNumPulses : Integer ;
         PNADCNum : Integer ;
         PNHoldingLevel : single ;
         PNSettlingTime : single ;
         PNInterPulse : single ;
         Unused1954 : array[1..12] of char ;

         ListEnable : Integer ;
         Unused1966 : array[1..80] of char ;

         end ;
procedure ImportFromDataFile( FileName : string ) ;
procedure ConvertpClampToWCP( FileName : string ) ;
procedure ConvertWCPTopClamp( FileName : string ) ;
procedure AppendWCPfile( const FileName : string ) ;
procedure ConvertCFSToWCP( FileName : string ) ;

implementation


procedure ImportFromDataFile( FileName : string ) ;
{ -----------------------------------------------------------------
  Determine the type of data file and convert it to a WCP data file
  -----------------------------------------------------------------}
Type
    TFileType = ( Unknown, pClampV5, pClampV6, CFS ) ;
var
   FileType : TFileType ;
   IdentNumber : Single ;
   IdentChar : Array[1..8] of char ;
   s : string ;
   FileHandle,i : Integer ;
   FilePointer : LongInt ;
begin
     { Open data file }
     FileHandle := FileOpen( FileName, fmOpenRead ) ;

     FileType := Unknown ;

     { Is it a PClamp V6 or later data file? }
     FilePointer := FileSeek( FileHandle, 0, 0 ) ;
     if FileRead(FileHandle,IdentChar,Sizeof(IdentChar))
        = Sizeof(IdentChar) then begin
        s := '' ;
        for i := 1 to High(IdentChar) do s := s + IdentChar[i] ;
        if (Pos('ABF',s) > 0) or (Pos('CPLX',s) > 0) or (Pos('FTCX',s) > 0) then
           FileType := pClampV6 ;
        end ;

     { Is it a PClamp V5 data file? }
     FilePointer := FileSeek( FileHandle, 0, 0 ) ;
     if FileRead(FileHandle,IdentNumber,Sizeof(IdentNumber))
        = Sizeof(IdentNumber) then begin
        if (IdentNumber = 1. ) or (IdentNumber = 10. ) then FileType := pClampV5 ;
        end ;

     { Is it a CED Filing System data file? }
     FilePointer := FileSeek( FileHandle, 0, 0 ) ;
     if FileRead(FileHandle,IdentChar,Sizeof(IdentChar))
        = Sizeof(IdentChar) then begin
        s := '' ;
        for i := 1 to High(IdentChar) do s := s + IdentChar[i] ;
        if (Pos('CEDFILE',s) > 0) then FileType := CFS ;
        end ;

     { Close data file }
     FileClose( FileHandle) ;
     { Import the file using the appropriate procedure }
     case FileType of
          pClampV6 : ConvertpClampToWCP( FileName ) ;
          pClampV5 : ConvertpClampToWCP( FileName ) ;
          CFS : ConvertCFSToWCP( FileName ) ;
          Unknown : begin
                  ImportFrm.FileName := FileName ;
                  ImportFrm.ShowModal ;
                  end ;
          end ;
     end ;


procedure ConvertpClampToWCP( FileName : string ) ;
{ ---------------------------------------------
  Convert a pClamp data file into WCP data file
  ---------------------------------------------}
var
   DataStartsAtByte,FilePointer,nw,NumRecordsToCopy,NumBytesPerRecord : LongInt ;
   Rec : LongInt ;
   FileHandle,pcChan,i : Integer ;
   ADCScale : single ;
   OK,pClampV6 : boolean ;
   ch : Integer ;
   FileType : string ;
   Buf : ^TIntArray ;
   rH : ^TRecHeader ;
   PC6Header : ^TABF ;
   PC5Header : ^TpClampV5 ;
   x : single ;
begin

     New(Buf) ;
     New(rH) ;
     New(pc6Header) ;
     New(pc5Header);

     { Close existing WCP data file }
     if RawFH.FileHandle > 0 then FileClose( RawFH.FileHandle ) ;
     { Create name of WCP file to hold pCLAMP file }
     RawFH.FileName := ReplaceFileEnding( FileName, '.wcp' ) ;

     OK := True ;

     { Open pClamp file }
     FileHandle := FileOpen( FileName, fmOpenRead ) ;

     { Read header block as ABF file header (PClamp V6 and later) }
     FilePointer := FileSeek( FileHandle, 0, 0 ) ;
     nw := FileRead(FileHandle,pc6Header^,Sizeof(pc6Header^)) ;
     pClampV6 := False ;

     { Check file type }
     FileType := '' ;
     for i := 1 to 4 do FileType := FileType + pc6Header^.FileType[i] ;
     if (FileType = 'ABF ') or (FileType = 'CPLX')
        or (FileType = 'FTCX') then pClampV6 := True ;

     { If this is not a pClamp V6 (Axon Binary File), try as pClamp V5 }
     if not pClampV6 then begin
           { Read header block as pClamp 5 file }
           FilePointer := FileSeek( FileHandle, 0, 0 ) ;
           nw := FileRead(FileHandle,pc5Header^,Sizeof(pc5Header^)) ;
           if pc5Header^.par[0] = 1. then FileType := 'CLPX'
           else if pc5Header^.par[0] = 10. then FileType := 'FTCX'
           else OK := False ;
           end ;

     { Extract data from pCLAMP header block }
     if OK then begin
        if( pClampV6 ) then begin

            { pClamp V6 data file }

            RawFH.NumChannels := MaxInt([pc6Header^.ADCNumChannels,1]) ;
            if pc6Header^.NumSamplesPerEpisode <= 0 then
               pc6Header^.NumSamplesPerEpisode := 512 ;
            NumBytesPerRecord := pc6Header^.NumSamplesPerEpisode*2 ;

            { Set WCP record size large enough to hold imported record }
            RawFH.NumSamples := 256 ;
            while RawFH.NumSamples <
                  (pc6Header^.NumSamplesPerEpisode div RawFH.NumChannels) do
                  RawFH.NumSamples := RawFH.NumSamples + 256 ;

            NumRecordsToCopy := pc6Header^.ActualAcqLength div
     	                        pc6Header^.NumSamplesPerEpisode ;
            RawFH.dt := pc6Header^.ADCSampleInterval*1E-6*RawFH.NumChannels ;
            RawFH.ADCVoltageRange := pc6Header^.ADCRange ;
            ADCScale := (2.*pc6Header^.ADCResolution) / 4096. ;
            RawFH.IdentLine := '' ;
            for i := 1 to 56 do RawFH.IdentLine := RawFH.IdentLine
                                             + pc6Header^.FileComment[i] ;

            { Channel scaling/units information }

            for ch := 0 to RawFH.NumChannels-1 do begin

                { Get PClamp physical channel number for this channel }
                pcChan := pc6Header^.ADCSamplingSeq[ch] ;

     	        Channel[ch].ADCCalibrationFactor := pc6Header^.InstrumentScaleFactor[pcChan]
                                                    * pc6Header^.SignalGain[pcChan] ;

                { Add "AddIt" gain if in use for this channel }
                if pc6Header^.AutoSampleADCNum = pcChan then
                   Channel[ch].ADCCalibrationFactor := Channel[ch].ADCCalibrationFactor
                                                       * pc6Header^.AutosampleAdditGain ;

                if Channel[ch].ADCCalibrationFactor = 0. then
                   Channel[ch].ADCCalibrationFactor := 1. ;

                Channel[ch].ADCAmplifierGain := 1. ;
	        Channel[ch].ADCZero := 0 ;
                Channel[ch].ADCUnits := '' ;

                for i := 1 to 4 do Channel[ch].ADCUnits := Channel[ch].ADCUnits +
                                                        pc6Header^.ADCUnits[pcChan,i] ;
                Channel[ch].ADCName := '' ;
	        for i := 1 to 4 do Channel[ch].ADCName := Channel[ch].ADCName +
                                                    pc6Header^.ADCChannelName[pcChan,i] ;

                Channel[ch].ChannelOffset := ch ;
                end ;

            { Get byte offset of data section }
            DataStartsAtByte := pc6Header^.DataSectionPtr*512 ;

            end
        else begin
            { pCLAMP V5 data file }
     	    RawFH.NumChannels := MaxInt([Trunc(pc5Header^.par[1]),1]) ;
            RawFH.NumSamples := Trunc(pc5Header^.par[2]) div RawFH.NumChannels ;
            NumBytesPerRecord := Trunc(pc5Header^.par[2])*2 ;
	    NumRecordsToCopy := Trunc(pc5Header^.par[3]) ;
	    RawFH.dt := pc5Header^.par[4]*1E-6*RawFH.NumChannels ;
            RawFH.ADCVoltageRange := pc5Header^.par[52] ;
            ADCScale := Power(2.,pc5Header^.par[54]) / 4096. ;
            if ADCScale = 0. then ADCScale := 1. ;
	    RawFH.IdentLine := '' ;
            for i := 1 to 76 do RawFH.IdentLine := RawFH.IdentLine
                                             + pc5Header^.Comment[i] ;

            { Channel scaling/units information }
            pcChan := Trunc ( pc5Header^.par[31] ) ;
            for ch := 0 to RawFH.NumChannels-1 do begin
                Channel[ch].ChannelOffset := ch ;
                Channel[ch].ADCAmplifierGain := 1. ;
                Channel[ch].ADCCalibrationFactor := pc5Header^.ADCGain[pcChan] ;
	        Channel[ch].ADCZero := 0 ;
                Channel[ch].ADCUnits := '' ;
                for i := 1 to 4 do Channel[ch].ADCUnits := Channel[ch].ADCUnits
                                                     + pc5Header^.Units[pcChan,i] ;
                Channel[ch].ADCName := Format( 'Ch.%d', [ch] ) ;
                Inc(pcChan) ;
                end ;
            DataStartsAtByte := 2*512 ;
            end ;
        end ;

     { Copy signal records from pCLAMP to WCP data file }

     if OK then begin
        { Create a new WCP file to hold converted data }
        RawFH.FileHandle := FileCreate( RawFH.FileName ) ;

        RawFH.NumRecords := 0 ;

        { Move file pointer to data section of pClamp file }
        FilePointer := FileSeek( FileHandle, DataStartsAtByte, 0 ) ;
        { Copy records }
        for Rec := 1 to NumRecordsToCopy do begin

            { Clear buffer (in case pCLAMP record is smaller than WCP record) }
            for i := 0 to (RawFH.NumSamples*RawFH.NumChannels)-1 do Buf^[i] := 0 ;

            { Read A/D samples from pClamp file }
            FilePointer := FileSeek( FileHandle,
                                     DataStartsAtByte+(Rec-1)*NumBytesPerRecord,
                                     0 ) ;
            nw := FileRead( FileHandle, Buf^, NumBytesPerRecord ) ;

            { Re-scale data }
            for i := 0 to (RawFH.NumSamples*RawFH.NumChannels)-1 do
                Buf^[i] := Trunc( Buf^[i]/ADCScale ) ;

            { Save record to file }
            Inc(RawFH.NumRecords) ;
            rH^.Status := 'ACCEPTED' ;
            rH^.RecType := 'TEST' ;
            rH^.Number := RawFH.NumRecords ;
            rH^.Time := rH^.Number ;
            rH^.dt := RawfH.dt ;
            rH^.Ident := ' ' ;
            for ch := 0 to RawFH.NumChannels do rH^.ADCVoltageRange[ch] :=
                                                RawFH.ADCVoltageRange ;
            rH^.Equation.Available := False ;
            rH^.Analysis.Available := False ;
            PutRecord( RawfH, rH^, RawfH.NumRecords, Buf^ ) ;
            end ;

        { Save file header }
        SaveHeader( RawFH ) ;
        { Close and re-open WCP file }
        FileClose( RawFH.FileHandle ) ;
        RawFH.FileHandle := FileOpen( RawFH.FileName, fmOpenReadWrite ) ;

        WriteToLogFile( 'pClamp File : ' + FileName ) ;
        WriteToLogFile( 'converted to WCP file : ' + RawFH.FileName ) ;
        end ;

     { Close pClamp file }
     FileClose( FileHandle ) ;

     Dispose(pc5Header) ;
     Dispose(pc6Header) ;
     Dispose(rH) ;
     Dispose(Buf) ;

     end ;


procedure ConvertWCPTopClamp( FileName : string ) ;
{ ---------------------------------------------
  Convert a WCP data file into a pCLAMP ABF data file
  ---------------------------------------------}
var
   DataStartsAtByte,FilePointer,nw,NumRecordsWritten,NumBytesPerRecord : LongInt ;
   Rec : LongInt ;
   FileHandle,i,ch : Integer ;
   OldRange : single ;
   Buf : ^TIntArray ;
   rH : ^TRecHeader ;
   PC6Header : ^TABF ;
   s : string ;
   Day,Month,Year,Min,Hour,Sec,Msec : Word ;
   lDay,lMonth,lYear,lMin,lHour,lSec : LongInt ;
begin

     Screen.Cursor := crHourglass ;

     New(Buf) ;
     New(rH) ;
     New(pc6Header) ;

     { Open new pClamp file }
     FileHandle := FileCreate( FileName ) ;

     if FileHandle < 0 then begin
        MessageDlg('Cannot create file ' + FileName, mtError,[mbOK],0) ;
        end
     else begin

          pc6Header^.FileType[1] := 'A' ;
          pc6Header^.FileType[2] := 'B' ;
          pc6Header^.FileType[3] := 'F' ;
          pc6Header^.FileType[4] := ' ' ;

          pc6Header^.FileVersionNumber := 1.1 ;
          pc6Header^.OperationMode := 5 ;
          pc6Header^.NumPointsIgnored := 0 ;

          DecodeDate( Now, Year, Month, Day ) ;
          lDay := Day ;
          lMonth := Month ;
          lYear := Year ;
          pc6Header^.FileStartDate := lDay + 100*lMonth + 10000*lYear ;
          DecodeTime( Now, Hour, Min, Sec, MSec ) ;
          lHour := Hour ;
          lMin := Min ;
          lSec := Sec ;
          pc6Header^.FileStartTime := lHour*3600 + lMin*60 + lSec ;

          pc6Header^.StopwatchTime := 0 ;
          pc6Header^.HeaderVersionNumber := 1.1 ;
          pc6Header^.nFileType := 1 ;
          pc6Header^.MSBinFormat := 0 ;

          pc6Header^.DataSectionPtr := 4 ;
          pc6Header^.TagSectionPtr := 0 ;
          pc6Header^.NumTagEntries := 0 ;
          pc6Header^.LongDescriptionPtr := 0 ;
          pc6Header^.LongDescriptionLines := 0 ;
          pc6Header^.DACFilePtr := 0 ;
          pc6Header^.DACFileNumEpisodes := 0 ;
          pc6Header^.DeltaArrayPtr := 0 ;
          pc6Header^.NumDeltas := 0 ;
          pc6Header^.NotebookPtr := 0 ;
          pc6Header^.NotebookManEntries := 0 ;
          pc6Header^.NotebookAutoEntries := 0 ;
          pc6Header^.SynchArrayPtr := 0 ;
          pc6Header^.SynchArraySize := 0 ;
          pc6Header^.DataFormat := 0 ;

          pc6Header^.ADCNumChannels := FH.NumChannels ;
          pc6Header^.ADCSampleInterval := ( FH.dt * 1E6 ) / FH.NumChannels ; {in microsecs}
          pc6Header^.ADCSecondSampleInterval := 0. ;
          pc6Header^.SynchTimeUnit := 0. ;
          pc6Header^.SecondsPerRun := 0 ;
          pc6Header^.NumSamplesPerEpisode := FH.NumSamples*FH.NumChannels ;
          pc6Header^.PreTriggerSamples := 50 ;
          pc6Header^.EpisodesPerRun := 1 ;
          pc6Header^.RunsPerTrial := 1 ;
          pc6Header^.NumberofTrials := 1 ;
          pc6Header^.AveragingMode := 0 ;
          pc6Header^.UndoRunCount := -1 ;
          pc6Header^.FirstEpisodeInRun := 1 ;
          pc6Header^.TriggerThreshold := 100 ;
          pc6Header^.TriggerSource := -2 ;
          pc6Header^.TriggerAction := 0 ;
          pc6Header^.TriggerPolarity := 0 ;
          pc6Header^.ScopeOutputInterval := 0. ;
          pc6Header^.EpisodeStartToStart := 1. ;
          pc6Header^.RunStartToStart := 1. ;
          pc6Header^.TrialStartToStart := 1. ;
          pc6Header^.AverageCount := 1 ;

          pc6Header^.DrawingStrategy := 1 ;
          pc6Header^.TiledDisplay := 0 ;
          pc6Header^.DataDisplayMode := 1 ;
          pc6Header^.DisplayAverageUpdate := -1 ;
          pc6Header^.ChannelStatsStrategy := 1 ;
          pc6Header^.CalculationPeriod := 16384 ;
          pc6Header^.SamplesPerTrace := FH.NumSamples ;
          pc6Header^.StartDisplayNum := 1 ;
          pc6Header^.FinishDisplayNum := 0 ;
          pc6Header^.MultiColor := 1 ;
          pc6Header^.ShowPNRawData := 0 ;

          pc6Header^.ADCRange := FH.ADCVoltageRange ;
          pc6Header^.DACRange := 10.24 ;
          pc6Header^.ADCResolution := 2048 ;
          pc6Header^.DACResolution := 2048 ;
          pc6Header^.AutoSampleEnable := 0 ;
          pc6Header^.AutoSampleAddItGain := 1. ;
          pc6Header^.AutoSampleADCNum := 0 ;

          pc6Header^.ExperimentType := 0 ;
          pc6Header^.AutoSampleEnable := 0 ;
          pc6Header^.AutoSampleADCNum := 0 ;
          pc6Header^.AutoSampleInstrument := 0 ;
          pc6Header^.AutoSampleAddItGain := 1. ;
          pc6Header^.AutoSampleFilter := 100000. ;
          pc6Header^.AutoSampleMembraneCap := 1. ;

          pc6Header^.ManualInfoStrategy := 0 ;
          pc6Header^.CellID1 := 1. ;
          pc6Header^.CellID2 := 2. ;
          pc6Header^.CellID3 := 3. ;

          { Name of program which created file }
          s := 'WinWCP' ;
          for i := 1 to High(pc6Header^.CreatorInfo) do begin
              pc6Header^.CreatorInfo[i] := ' ' ;
              if i < Length(s) then pc6Header^.CreatorInfo[i] := s[i];
              end ;

          { Experiment ident information }
          for i := 1 to High(pc6Header^.FileComment) do begin
              pc6Header^.FileComment[i] := ' ' ;
              if i < Length(FH.IdentLine) then
                 pc6Header^.FileComment[i] := FH.IdentLine[i];
              end ;

          { Analog input channel settings }

          for ch := 0 to 15 do begin

	      pc6Header^.ADCPToLChannelMap[ch] := ch ;
	      pc6Header^.ADCSamplingSeq[ch] := -1 ;

              for i := 1 to 10 do pc6Header^.ADCChannelName[ch,i] := ' ' ;
              s := format( 'Ch%d ',[ch] ) ;
              for i := 1 to 4 do pc6Header^.ADCChannelName[ch,i] := s[i] ;

              for i := 1 to 8 do pc6Header^.ADCUnits[ch,i] := ' ' ;
	      pc6Header^.ADCUnits[ch,1] := 'm' ;
              pc6Header^.ADCUnits[ch,2] := 'V' ;

	      pc6Header^.ProgrammableGain[ch] := 1. ;
	      pc6Header^.DisplayAmplification[ch] := 1. ;
	      pc6Header^.DisplayOffset[ch] := 0. ;
	      pc6Header^.InstrumentScaleFactor[ch] := 1. ;
	      pc6Header^.InstrumentOffset[ch] := 0. ;
	      pc6Header^.SignalGain[ch] := 1. ;
	      pc6Header^.SignalOffset[ch] := 0. ;
	      pc6Header^.SignalLowpassFilter[ch] := 100000. ;
	      pc6Header^.SignalHighpassFilter[ch] := 0. ;
              end ;

          { Analog output channel settings }

          for ch := 0 to 3 do begin
              for i := 1 to 10 do pc6Header^.DACChannelName[ch,i] := ' ' ;
              for i := 1 to 8 do pc6Header^.DACChannelUnits[ch,i] := ' ' ;
              pc6Header^.DACScaleFactor[ch] := 1. ;
              pc6Header^.DACHoldingLevel[ch] := 0. ;
              end ;

          pc6Header^.SignalType := 0 ;

          pc6Header^.OutEnable := 0 ;
          pc6Header^.SampleNumberOUT1 := 0 ;
          pc6Header^.SampleNumberOUT2 := 0 ;
          pc6Header^.FirstEpisodeOUT := 0 ;
          pc6Header^.LastEpisodeOut := 0 ;
          pc6Header^.PulseSamplesOUT1 := 0 ;
          pc6Header^.PulseSamplesOUT2 := 0 ;

          pc6Header^.DigitalEnable := 0 ;
          pc6Header^.WaveformSource := 0 ;
          pc6Header^.ActiveDACChannel := 0 ;
          pc6Header^.InterEpisodeLevel := 0 ;
          for i := 0 to High(pc6Header^.EpochType) do begin
              pc6Header^.EpochType[i] := 0 ;
              pc6Header^.EpochInitLevel[i] := 0. ;
              pc6Header^.EpochLevelInc[i] := 0. ;
              pc6Header^.EpochInitDuration[i] := 0 ;
              pc6Header^.EpochDurationInc[i] := 0 ;
              end ;
          pc6Header^.DigitalHolding := 0 ;
          pc6Header^.DigitalInterEpisode := 0 ;
          for i := 0 to High(pc6Header^.DigitalValue) do
              pc6Header^.DigitalValue[i] := 0 ;

          pc6Header^.DACFileStatus := 1. ;
          pc6Header^.DACFileOffset := 0. ;
          pc6Header^.DACFileAutoScale := 0 ;
          pc6Header^.DACFileEpisodeNum := 0 ;
          pc6Header^.DACFileADCNum := 0 ;
          for i := 1 to High(pc6Header^.DACFileName) do
              pc6Header^.DACFileName[i] := ' ' ;
          for i := 1 to High(pc6Header^.DACFilePath) do
              pc6Header^.DACFilePath[i] := ' ' ;

          pc6Header^.ConditEnable := 0 ;
          pc6Header^.ConditChannel := 0 ;
          pc6Header^.ConditNumPulses := 0 ;
          pc6Header^.BaselineDuration := 1. ;
          pc6Header^.BaselineLevel := 0. ;
          pc6Header^.StepDuration := 1. ;
          pc6Header^.StepLevel := 0. ;
          pc6Header^.PostTrainPeriod := 1. ;
          pc6Header^.PostTrainLevel := 1. ;

          pc6Header^.ParamToVary := 0 ;
          for i := 1 to High(pc6Header^.ParamValueList) do
              pc6Header^.ParamValueList[i] := ' ' ;

          pc6Header^.AutoPeakEnable := 0 ;
          pc6Header^.AutoPeakPolarity := 0 ;
          pc6Header^.AutoPeakADCNum := 0 ;
          pc6Header^.AutoPeakSearchMode := 0 ;
          pc6Header^.AutoPeakStart := 0 ;
          pc6Header^.AutoPeakEnd := 0 ;
          pc6Header^.AutoPeakSmoothing := 1 ;
          pc6Header^.AutoPeakBaseline := -2 ;
          pc6Header^.AutoPeakAverage := 0 ;

          pc6Header^.ArithmeticEnable := 0 ;
          pc6Header^.ArithmeticUpperLimit := 1. ;
          pc6Header^.ArithmeticLowerLimit := 0. ;
          pc6Header^.ArithmeticADCNumA := 0 ;
          pc6Header^.ArithmeticADCNumB := 0 ;
          pc6Header^.ArithmeticK1 := 1. ;
          pc6Header^.ArithmeticK2 := 2. ;
          pc6Header^.ArithmeticK3 := 3. ;
          pc6Header^.ArithmeticK4 := 4. ;
          pc6Header^.ArithmeticOperator[1] := '+' ;
          pc6Header^.ArithmeticOperator[2] := ' ' ;
          for i := 1 to High(pc6Header^.ArithmeticUnits) do
              pc6Header^.ArithmeticUnits[i] := ' ' ;
          pc6Header^.ArithmeticK5 := 5. ;
          pc6Header^.ArithmeticK6 := 6. ;
          pc6Header^.ArithmeticExpression := 0 ;

          pc6Header^.PNEnable := 0 ;
          pc6Header^.PNPosition := 0 ;
          pc6Header^.PNPolarity := 1 ;
          pc6Header^.PNNumPulses := 4 ;
          pc6Header^.PNADCNum := 0 ;
          pc6Header^.PNHoldingLevel := 0. ;
          pc6Header^.PNSettlingTime := 100. ;
          pc6Header^.PNInterPulse := 100. ;

          pc6Header^.ListEnable := 0 ;

          { Channel scaling/units information }

          for ch := 0 to RawFH.NumChannels-1 do begin
              pc6Header^.ADCSamplingSeq[ch] := Channel[ch].ChannelOffset ;
              pc6Header^.SignalGain[ch] := 1. ;
              pc6Header^.InstrumentScaleFactor[ch] := Channel[ch].ADCCalibrationFactor /
                                                      Channel[ch].ADCAmplifierGain ;

              for i := 1 to 8 do if i <= Length(Channel[ch].ADCUnits) then
                  pc6Header^.ADCUnits[ch,i] := Channel[ch].ADCUnits[i] ;

              for i := 1 to 10 do if i <= Length(Channel[ch].ADCName) then
                  pc6Header^.ADCChannelName[ch,i] := Channel[ch].ADCName[i] ;

              end ;

          { Write header block }
          FilePointer := FileSeek( FileHandle, 0, 0 ) ;
          nw := FileWrite(FileHandle,pc6Header^,Sizeof(pc6Header^)) ;

          { Copy signal records from pCLAMP to WCP data file }

          NumBytesPerRecord := FH.NumSamples*FH.NumChannels*2 ;

          { Move file pointer to data section of pClamp file }
          DataStartsAtByte := 4*512 ;
          FilePointer := FileSeek( FileHandle, DataStartsAtByte, 0 ) ;

          { Copy records }
          NumRecordsWritten := 0 ;
          OldRange := -1. ;
          for Rec := 1 to FH.NumRecords do begin
              { Read record from WCP file }
              GetRecord( FH, rH^, Rec, Buf^ ) ;
              { Only export, if it is accepted }
              if rH^.Status = 'ACCEPTED' then begin

                 { Get A/D voltage range from record }
                 pc6Header^.ADCRange := rH^.ADCVoltageRange[0] ;

                 { Note, if records do not have same A/D voltage range,
                   their will be scaling errors in the pCLAMP file }
                 if (OldRange <> pc6Header^.ADCRange) and (OldRange <> -1. ) then
                    MessageDlg(
                    'Data file incompatible. ABF records incorrectly scaled.',
                    mtWarning,[mbOK],0);
                 OldRange := pc6Header^.ADCRange ;

                 Inc(NumRecordsWritten) ;

                 { Write A/D samples to pClamp file }
                 nw := FileWrite( FileHandle, Buf^, NumBytesPerRecord ) ;

                 end ;
              end ;

          { Correct Instrument Scale Factor entry for any differences between
            A/D voltage ranges within record }
          for ch := 0 to FH.NumRecords-1 do
              pc6Header^.InstrumentScaleFactor[ch] :=  pc6Header^.InstrumentScaleFactor[ch]
                                                  * (rH^.ADCVoltageRange[ch]/
                                                     rH^.ADCVoltageRange[0] ) ;

          { Update header with number of records written }
          pc6Header^.ActualAcqLength := FH.NumSamples*FH.NumChannels*NumRecordsWritten ;
          pc6Header^.ActualEpisodes := NumRecordsWritten ;
          FilePointer := FileSeek( FileHandle, 0, 0 ) ;
          nw := FileWrite(FileHandle,pc6Header^,Sizeof(pc6Header^)) ;

          WriteToLogFile( 'File : ' + FH.FileName ) ;
          WriteToLogFile( 'converted to pCLAMP (ABF) file : ' + FileName ) ;

          { Close pClamp file }
          FileClose( FileHandle ) ;
          end ;

     Dispose(pc6Header) ;
     Dispose(rH) ;
     Dispose(Buf) ;

     Screen.cursor := crDefault ;

     end ;


procedure AppendWCPfile( const FileName : string ) ;
{ ----------------------------------------------------------
  Append the records from a WCP data file to the current one
  ----------------------------------------------------------}
var
   Buf : ^TIntArray ;
   RecHeader : ^TRecHeader ;
   OK : Boolean ;
   ch : Integer ;
   Rec,StartAt : LongInt ;
   KeepChannel : Array[0..ChannelLimit] of TChannel ;
   YScale : Array[0..ChannelLimit] of Single ;
   ScaleFrom,ScaleTo : Single ;
   AppFH : TFileHeader ;
begin
     { Create buffers }
     New(RecHeader) ;
     New(Buf) ;

     { Save signal channel settings for currently open file }
     for ch := 0 to RawFH.NumChannels-1 do KeepChannel[ch] := Channel[ch] ;

     { Open file to be appended }
     AppFH.FileName := FileName ;
     AppFH.FileHandle := FileOpen( AppFH.FileName, fmOpenReadWrite ) ;
     GetHeader( AppFH ) ;

     if (AppFH.NumSamples = RawFH.NumSamples)
        and (AppFH.NumChannels = RawFH.NumChannels ) then OK := True
     else begin
         OK := False ;
         MessageDlg('File ' + FileName + 'Not compatible.',mtWarning,[mbOK],0) ;
         end ;

     if OK then begin

        { if the calibration factors of the appended file are different
          apply a correction factor to the A/D voltage range in each record }
                     { Adjust for possible differences in channel calibration factors }
        for ch := 0 to AppFH.NumChannels-1 do begin
                 ScaleFrom := Channel[ch].ADCCalibrationFactor *
                              Channel[ch].ADCAmplifierGain ;
                 ScaleTo := KeepChannel[ch].ADCCalibrationFactor *
                            KeepChannel[ch].ADCAmplifierGain ;
                 YScale[ch] := ScaleTo / ScaleFrom ;
                 end ;

        { Append records to end of current data file }
        StartAt := RawFH.NumRecords + 1 ;
        for Rec := 1 to AppFH.NumRecords do begin
            { Read from source file }
            GetRecord( AppfH, RecHeader^, Rec, Buf^ ) ;
            { Re-scale calibration }
            for ch := 0 to AppFH.NumChannels-1 do
                RecHeader^.ADCVoltageRange[ch] := RecHeader^.ADCVoltageRange[ch] *
                                                 YScale[ch] ;
            { Write to destination file }
            if RecHeader^.Status = 'ACCEPTED' then begin
               Inc( RawFH.NumRecords ) ;
               PutRecord( RawfH, RecHeader^, RawFH.NumRecords, Buf^ ) ;
               end ;
            end ;

        WriteToLogFile( AppFH.FileName + ' appended to ' + RawFH.FileName ) ;
        WriteToLogFile( format( 'Records %d - %d added (%d)',
                        [StartAt,RawFH.NumRecords,RawFH.NumRecords-StartAt+1]));

        end ;

     { Restore signal channel settings for currently open file }
     for ch := 0 to RawFH.NumChannels-1 do Channel[ch] := KeepChannel[ch] ;

     { Dispose of buffers }
     Dispose(RecHeader) ;
     Dispose(Buf) ;

     { Close source file }
     FileClose( AppFH.FileHandle ) ;

     { Update destination file header }
     SaveHeader( RawFH ) ;

     end ;


procedure ConvertCFSToWCP( FileName : string ) ;
{ ------------------------------------------------------------------
  Convert a Cambridge Electronic Design data file into WCP data file
  ------------------------------------------------------------------}
const
     Scale16To12Bit = 16 ;
type
    TChannelDef = record
                ChanName : String[21] ;
                UnitsY : String[9] ;
                UnitsX : String[9] ;
                dType : Byte ;
	        dKind : Byte ;
	        dSpacing : Word ;
                OtherChan : Word ;
                end ;

    TChannelInfo = record
	        DataOffset : LongInt ; {offset to first point}
	        DataPoints : LongInt ; {number of points in channel}
	        scaleY : single ;
	        offsetY : single ;
	        scaleX : single ;
	        offsetX : single ;
                end ;

    TDataHeader = record
	lastDS : LongInt ;
	dataSt : LongInt ;
	dataSz : LongInt ;
	Flags : Word ;
      	Space : Array[1..8] of Word ;
        end ;

    TCFSFileHeader = record
	Marker : Array[1..8] of char ;
	Name : Array[1..14] of char ;
	FileSz : LongInt ;
        TimeStr : Array[1..8] of char ;
	DateStr : Array[1..8] of char ;
	DataChans : Integer ;
	FilVars : Integer ;
	DatVars : Integer ;
	fileHeadSz : Integer ;
	DataHeadSz : Integer ;
	EndPnt : LongInt ;
	DataSecs : Integer ;
	DiskBlkSize : Integer ;
	CommentStr : String[73] ;
	TablePos : LongInt ;
	Fspace : Array[1..20] of Word ;
        end ;

var
   ChannelDef : TChannelDef ;
   ChannelInfo : TChannelInfo ;
   CFSFileHeader : TCFSFileHeader ;
   RecHeader : TDataHeader ;
   FilePointer,DataPointer : LongInt ;
   Rec : LongInt ;
   FileHandle,i,LastChannel,Src,Dest,SrcStep,iOff,nSamples : Integer ;
   ADCScale : single ;
   OK,Quit : boolean ;
   Ch : Integer ;
   Buf,CEDBuf : ^TIntArray ;
   rH : ^TRecHeader ;
   NumSamplesInChannel :  Array[0..ChannelLimit] of Integer ;
   DataOffset :  Array[0..ChannelLimit] of Integer ;
   SampleSpacing :  Array[0..ChannelLimit] of Integer ;
   x : single ;
   s : string ;
   TimeUnits : string ;
   TScale : single ;
begin

     try
        { Create buffers }
        New(Buf) ;
        New(rH) ;
        New(CEDBuf) ;

        { Close existing WCP data file }
        if RawFH.FileHandle > 0 then FileClose( RawFH.FileHandle ) ;
        { Create name of WCP file to hold CED file }
        RawFH.FileName := ReplaceFileEnding( FileName, '.wcp' ) ;

        OK := True ;

        { Open CFS data file }
        FileHandle := FileOpen( FileName, fmOpenRead ) ;

        {  Read CFS file header block }
        FilePointer := FileSeek( FileHandle, 0, 0 ) ;
        if FileRead(FileHandle,CFSFileHeader,Sizeof(CFSFileHeader))
           <> Sizeof(CFSFileHeader) then begin
           MessageDlg( FileName + ' - Header unreadable',mtWarning, [mbOK], 0) ;
           OK := False ;
           end ;

        { Check that this is a CFS data file }
        if OK then begin
           s := '' ;
           for i := 1 to High(CFSFileHeader.Marker) do
               s := s + CFSFileHeader.Marker[i] ;
           if Pos('CEDFILE',s) = 0 then begin
              MessageDlg( FileName + ' : Not a CFS data file',mtWarning,[mbOK],0) ;
              OK := False ;
              end ;
           end ;

        { Get data from header block }
        if OK then begin
            { No. of analog input channels held in file }
            if CFSFileHeader.DataChans > (ChannelLimit+1) then
               MessageDlg( format('Input channels 6-%d ignored',
                                         [CFSFileHeader.DataChans-1]),
                                         mtWarning, [mbOK], 0 ) ;
            { Number of analog input channels }
            RawFH.NumChannels := IntLimitTo( CFSFileHeader.DataChans,
                                             1, ChannelLimit+1 ) ;
            { Last channel number }
            LastChannel := RawFH.NumChannels - 1 ;

            { Get experiment identification text }
            RawFH.IdentLine := CFSFileHeader.CommentStr ;
            WriteToLogFile( 'CFS File : ' + FileName ) ;
	    WriteToLogFile( RawFH.IdentLine ) ;
	    WriteToLogFile( CFSFileHeader.TimeStr ) ;
	    WriteToLogFile( CFSFileHeader.DateStr ) ;

            { A/D converter input voltage range }
	    RawFH.ADCVoltageRange := 5. ;
            { Read Channel definition records }
	    for Ch := 0 to LastChannel do begin
                { Read signal channel definition record }
                if FileRead(FileHandle,ChannelDef,Sizeof(ChannelDef))
                   = Sizeof(ChannelDef) then begin
                   { Name of signal channel }
                   Channel[Ch].ADCName := ChannelDef.ChanName ;
                   { Units of signal channel }
                   Channel[Ch].ADCUnits := ChannelDef.UnitsY ;

                   { Time units }
                   TimeUnits := ChannelDef.UnitsX ;
                   { Determine scaling to secs factor }
                   if Pos( 'us', TimeUnits ) > 0 then TScale := 1E-6
                   else if Pos( 'ms', TimeUnits ) > 0 then TScale := 1E-3
                                                      else TScale := 1. ;

                   SampleSpacing[Ch] := ChannelDef.dSpacing ;
                   end
                else MessageDlg(
                     format( 'Ch.%d definition record unreadable',[Ch]),
                    mtWarning, [mbOK], 0 ) ;
                end ;
            end ;

        { Read data records from CFS file }
        if OK then begin

            { Create a new WCP file to hold converted data }
            RawFH.FileHandle := FileCreate( RawFH.FileName ) ;
            RawFH.NumRecords := 0 ;

	    for Rec := 1 to CFSFileHeader.DataSecs do begin

                { Get pointer to start of data record #Rec }
	        FilePointer := CFSFileHeader.TablePos + (Rec-1)*4 ;
                FilePointer := FileSeek( FileHandle, FilePointer, 0 ) ;
                FileRead(FileHandle,DataPointer,SizeOf(DataPointer)) ;

                { Read record data header }
                FilePointer := FileSeek( FileHandle, DataPointer, 0 ) ;
                FileRead(FileHandle,RecHeader,SizeOf(RecHeader)) ;

                { Read channel offset/scaling information records
                  which follow data record }
	        for Ch := 0 to LastChannel do begin

                    { Read channel definition record }
                    FileRead(FileHandle,ChannelInfo,SizeOf(ChannelInfo)) ;

                    { Derive WCP's calibration factors from first record
                      scaling factor }
                    If Rec = 1 then begin
                       { Get signal bits->units scaling factor }
                       Channel[ch].ADCScale := ChannelInfo.ScaleY * Scale16To12Bit ;
                       { Note. Multiplcation  by Scale16To12Bit to
                         account for conversion from
                         CED's +-32767 data range to +/-2048}
                       { Calculate calibration factors }
                       Channel[ch].ADCCalibrationFactor := rawFH.ADCVoltageRange /
                                      ( Channel[ch].ADCScale * (MaxADCValue+1) ) ;
                       Channel[ch].ADCAmplifierGain := 1. ;
                       end ;

                    { Correct record's input voltage range setting to
                      account for an changes in signal scaling }
                    rH^.ADCVoltageRange[Ch] := ( RawFH.ADCVoltageRange *
                                            ChannelInfo.ScaleY * Scale16To12Bit )
                                            / Channel[ch].ADCScale ;

                    { Offset into groups of A/D samples for this channel }
                    Channel[ch].ChannelOffset := Ch ;

                    { Inter sample interval }
		    RawFH.dt := ChannelInfo.scaleX*TScale ;
                    rH^.dt := RawfH.dt ;

                    { Number of samples in this channel }
		    NumSamplesInChannel[Ch] := ChannelInfo.DataPoints ;
                    { Offset (bytes) of samples for this channel in
                      record data area }
		    DataOffset[Ch] := ChannelInfo.DataOffset ;

                    end ;

                { Find a suitable number of samples per record }
		if Rec = 1 then begin
		    RawFH.NumSamples := 256 ;
                    Quit := False ;
		    while not Quit do begin
                       Quit := True ;
                       for Ch := 0 to LastChannel do begin
                           { Increase in steps of 256 }
                           if NumSamplesInChannel[Ch] > RawFH.NumSamples then begin
                              RawFH.NumSamples := RawFH.NumSamples + 256 ;
                              Quit := False ;
                              end ;
                           { Stop if buffer space limit reached }
                           if (RawFH.NumSamples*RawFH.NumChannels)
                              >= (MaxTBuf+1) then Quit := True ;
                           end ;
                       end ;
                    end ;

               { Read binary data from CED data file into CED record buffer }
               FilePointer := FileSeek( FileHandle,RecHeader.DataSt,0) ;
               FileRead( FileHandle, CEDBuf^, RecHeader.DataSz ) ;

               { Copy from CED buffer to WCP buffer }
	       for Ch := 0 to LastChannel do begin
                    { Increment between samples for this channel in CED buffer }
                    SrcStep := SampleSpacing[Ch] div 2 ;
                    { Number of samples for this channel }
                    nSamples := NumSamplesInChannel[Ch] ;
                    { Starting point of sample data in CED buffer }
                    Src := DataOffset[Ch] div 2 ;
                    { Place samples in WCP buffer starting here }
		    Dest := Channel[ch].ChannelOffset ;
		    for i := 1 to RawFH.NumSamples do begin
                        { Re-scale samples from 16 -> 12 bits }
			if( i <= nSamples ) then
                            Buf^[Dest] := (CEDBuf^[Src] div Scale16To12Bit )
                        else Buf^[Dest] := 0 ;
                        { Increment WCP buffer point by sample spacing }
			Dest := Dest + RawFH.NumChannels ;
                        { Increment CED buffer point by sample spacing }
			Src := Src + SrcStep ;
		        end ;
                    end ;

               { Save record to WCP data file }
               Inc(RawFH.NumRecords) ;
               rH^.Status := 'ACCEPTED' ;
               rH^.RecType := 'TEST' ;
               rH^.Number := RawFH.NumRecords ;
               rH^.Time := rH^.Number ;
               rH^.Ident := ' ' ;
               rH^.Equation.Available := False ;
               rH^.Analysis.Available := False ;
               PutRecord( RawfH, rH^, RawfH.NumRecords, Buf^ ) ;
               end ;

            { Save file header }
            SaveHeader( RawFH ) ;
            { Close and re-open WCP file }
            FileClose( RawFH.FileHandle ) ;
            RawFH.FileHandle := FileOpen( RawFH.FileName, fmOpenReadWrite ) ;


            WriteToLogFile( 'converted to WCP file : ' + RawFH.FileName ) ;

            end ;

     finally

            { Close CED file }
            FileClose( FileHandle ) ;
            { Free buffers }
            Dispose(rH) ;
            Dispose(Buf) ;
            Dispose(CEDBuf) ;
            end ;
     end ;




end.
