function piLineFailed = runPiLine( outputRecord17, outputResiduals, ...
                                   outputStatRange,  startPiHandle, refSV, ...
                                   decimationInterval, loadStartTime, ...
                                   loadStopTime, elevationMask, ...
                                   piStarControl, generatePiStar, ...
                                   simOutputStruct, simControlStruct, ...
                                   simNetworkStruct )
% $Id: runPiLine.m,v 1.8 2008/08/04 21:57:35 vnadkar Exp $
%
% Call piLineMex (dll) with options to create PiLine diagnostic data.
%
% Parameters passed:
% REQUIRED:
% outputRecord17:  flag, set = output record 17 style data.
% outputResiduals: flag, set = output double-diff phase/range/iono residuals.
% outputStatRange: flag, set = output stationary ranges.
% OPTIONAL:
% startPiHandle:   figure handle of piLab startup GUI. If this function is
%                  not called from a GUI, this is not passed, or set to []
%                  if additional parameters are passed.
% refSV:           reference SV for double-differencing.
%                  -1 = use highest elevation SV at the start of the
%                  data set.
% decimationInterval: interval for decimating survey data file, seconds.
%                  Passed as one, zero or [] will disable decimation.
% loadStartTime:   Start time for data loading, GPS seconds of week
% loadStopTime:    Stop  time for data loading, GPS seconds of week
%                  Time window disabled if start time = stop time, or
%                  both parameters passed as [].
%                  Usually passed as [] in piLab, and then loaded from
%                  the piStarControl structure. Passed as non-zero by
%                  non-piLab programs using this m-file.
% elevationMask:   elev mask for double-difference processing
%
% ..... Addition parameters used by piLab/piStar .....
% piStarControl    Structure of control parameters from the piStar.ini file.
%                  Passed as [] to attempt a load within this function.
% generatePiStar:  PiStar observations generation type.
%                  Can be passed as [].
% simOutputStruct: Array of structures containing simulated position info.
% simControlStruct: Structure of general control parameters for the
%                   observation generation.
% simNetworkStruct: Structure of control parameters including positions
%                   for the network stations and rover used for the
%                   observation generation.
%
% Parameters returned:
% piLineError: 0 = piLine execution complete
%              1 = piLine did not finish execution.
%              2 = This routine called with all option flags reset.
%
% In calling function, must set the following globals:
% 
% global phaseDDiffL1
% global phaseDDiffL2
% global phaseDDiffL2C
% global phaseDDiffL5
% global phaseDDiffGL1_CA
% global phaseDDiffGL1_P
% global phaseDDiffGL2
% global phaseDDiffGalL1   <-- New
% global phaseDDiffGalE5A  <-- New
% global phaseDDiffGalE5B  <-- New
% global phaseDDiffGalE5AB <-- New
% global ionoDDiff
% global rangeDDiffL1
% global rangeDDiffL2
% global rangeDDiffL2C
% global rangeDDiffL5
% global rangeDDiffGL1_CA
% global rangeDDiffGL1_P
% global rangeDDiffGL2
% global rangeDDiffGalL1   <-- New
% global rangeDDiffGalE5A  <-- New
% global rangeDDiffGalE5B  <-- New
% global rangeDDiffGalE5AB <-- New
% global statRangeL1
% global statRangeL2
% global statRangeL2C
% global statRangeL5
% global rec17DataL1
% global rec17DataL2
% global rec17DataL2C
% global rec17DataL5
% piLineParams structure fields:
%    refSV: 1x1 mxREAL array (from C double in PiLine)
%   stn1FileName: string (from C string in PiLine)
%   stn2FileName: string (from C string in PiLine)
%   antennaTypeBase:  1x1 mxREAL array (C double)
%   antennaTypeRover: 1x1 mxREAL array (C double)
% global piLineParams
% global datFileNames (optional)
% global piLineOutput (optional)

% Example of call to piLineMex:
% Run pi-line with options: -o340  4   = Stationary Range,
%                                 +16  = Record 17 data,
%                                 +64  = Extended Double Difference residuals
%                                 +256 = Extended Iono residuals.
%                           -f3  = L1, L2           (bit0 = L1, bit1 = L2)
%                     or... -f11 = L1, L2, L5       (bit3 = L5)
%                     or... -f27 = L1, L2, L2C, L5  (bit4 = L2C) *
%                           -r0 = Use the current highest SV as the reference.
% * See below for signals processed when Galileo is disabled/enabled.
%
% When Galileo is disabled, the following is processed:
% L1 =  L1-GPS + L1-GLONASS-C/A-CODE + L1-GLONASS-P-CODE
%       L2 =  L2E-GPS + L2-GLONASS-P-CODE
%       L2C = L2C-GPS
%       L5 =  L5-GPS
%
% When Galileo is enabled, the following is processed:
% L1 =  L1-GPS + L1-GLONASS-C/A-CODE + L1-GLONASS-P-CODE + L1-Galileo
%       L2 =  L2E-GPS + L2-GLONASS-P-CODE + E5B-Galileo 
%       L2C = L2C-GPS + E5A+B-Galileo
%       L5 =  L5-GPS  + E5A-Galileo 
%
% See definition of d_ENABLE_L2_AND_L2C for special testing.


global dummy
%%%%%%%%%% Global data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
global phaseDDiffL1  % Transferred from PiLine mex file.
global phaseDDiffL2  % Transferred from PiLine mex file.
global phaseDDiffL2C % Transferred from PiLine mex file.
global phaseDDiffL5  % Transferred from PiLine mex file.
global phaseDDiffGL1_CA
global phaseDDiffGL1_P
global phaseDDiffGL2
global phaseDDiffGalL1
global phaseDDiffGalE5A
global phaseDDiffGalE5B
global phaseDDiffGalE5AB
global ionoDDiff     % Transferred from PiLine mex file.
global rangeDDiffL1  % Transferred from PiLine mex file.
global rangeDDiffL2  % Transferred from PiLine mex file.
global rangeDDiffL2C % Transferred from PiLine mex file.
global rangeDDiffL5  % Transferred from PiLine mex file.
global rangeDDiffGL1_CA
global rangeDDiffGL1_P
global rangeDDiffGL2
global rangeDDiffGalL1
global rangeDDiffGalE5A
global rangeDDiffGalE5B
global rangeDDiffGalE5AB
global statRangeL1   % Transferred from PiLine mex file.
global statRangeL2   % Transferred from PiLine mex file.
global rangeDDiffLC  % Transferred from PiLine mex file.
global statRangeL5   % Transferred from PiLine mex file.
global rec17DataL1   % Transferred from PiLine mex file.
global rec17DataL2   % Transferred from PiLine mex file.
global rangeDDiffLC  % Transferred from PiLine mex file.
global rec17DataL5   % Transferred from PiLine mex file.
% piLineParams structure fields:
%   refSV: 1x1 mxREAL array (C double)
%   stn1FileName: string (C string)
%   stn2FileName: string (C string)
%   antennaTypeBase:  1x1 mxREAL array (C double)
%   antennaTypeRover: 1x1 mxREAL array (C double)
global piLineParams  % Transferred from PiLine mex file.

global datFileNames
global piLineOutput


%%%%%%%%%% Initialization %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
piLineFailed = 0 ;  % Default to OK.
iniFileNameStr = 'piStar.ini' ;

% PiStar observation generation type.
d_PISTAR_REGENERATION = 1 ;  % Move current observations to a new position.
d_PISTAR_GENERATION = 2 ;    % Generate new observations.
% Large decimation as data ignored. Data file only read for emphemerides.
d_PISTAR_DECIMATION_STR = '-d600' ;

d_ENABLE_L2_AND_L2C = 1 ; % Enable processing of GPS L2C if available.
d_ENABLE_GALILEO = 0 ;    % Enable processing of Galileo if available.

if d_ENABLE_L2_AND_L2C
% Process both L2-classic and L2-civil. This is for special testing, and
% usually the L2-civil will replace the L2-classic in production receivers.
% This also means process both Galileo E5B and E5A+B/AltBOC.
 freqStr = '-f27' ;
else
 freqStr = '-f11' ;  % L1, L2, L5.
end

if d_ENABLE_GALILEO
  GNSSenableStr = '-g' ;
else
% Dummy flag ? is ignored by PiLine.
% Passing the empty string '' causes a problem with PiLine.
  GNSSenableStr = '?' ;
end


%%%%%%%%%% Check input arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin >= 4 & ~isempty( startPiHandle )
% Uing a GUI, startPiHandle is available.
  guiEnabled = 1 ;
  guiData = guidata( startPiHandle ) ;  % Retrieve data stored in the GUI.
else
  guiEnabled = 0 ;
end

% Check whether refSV (reference SV) was passed.
if nargin < 5 | isempty( refSV )
  if guiEnabled
    if isfinite( guiData.piLineConfig.refSV )
      refSV = guiData.piLineConfig.refSV ;
    else
      refSV = 0 ;
    end
  else
    refSV = 0 ;
  end
end
refSVStr = num2str( refSV ) ;

if nargin < 6 | isempty( decimationInterval )
  if guiEnabled
    decimationInterval = guiData.piLineConfig.decimationInterval ;
  else
    decimationInterval = [] ;
  end
end

if nargin < 7 | isempty( loadStartTime )
  loadStartTime = [] ;
end

if nargin < 8 | isempty( loadStopTime )
  loadStopTime = [] ;
end

if nargin < 9 | isempty( elevationMask )
  if guiEnabled
    elevationMask = guiData.piLineConfig.elevMask ;
  else
    elevationMask = 0 ;
  end
end

if nargin < 10
  piStarControlEnabled = 0 ;
else
  piStarControlEnabled = 1 ;  % Will use control parameters from piStarControl.
end

if nargin < 11 | isempty( generatePiStar )
  generatePiStar = 0 ;  % Not selected PiStar data generation.
end

if nargin < 12 | isempty( simOutputStruct )
  simOutputStruct = [] ;  % Not selected PiStar data generation.
end

if nargin < 13 | isempty( simControlStruct )
  simControlStruct = [] ;  % Not selected PiStar data generation.
end

if nargin < 14 | isempty( simNetworkStruct )
  simNetworkStruct = [] ;  % Not selected PiStar data generation.
end

if piStarControlEnabled & isempty( piStarControl )
% An empty piStarControl has been passed indicating a desire to use it,
% but it has not been loaded. This occurs for direct GUI pull down menu
% commands to run PiLine (not the full window GUI for PiLine).
% Load piStar.ini file.
  [ piStarControl,  error ] = parseIniFile( startPiHandle ) ;

  if error  % Unable to open piStar.ini file.
    piLineFailed = 1 ;  % Returned value.
    return ;
  else
    piStarControlEnabled  = 1 ;
  end ;
end

% Update load start/stop times if provided via piStarControl structure.
if piStarControlEnabled
  if isempty( loadStartTime )
   loadStartTime = piStarControl.loadStartTime ;
  end
  if isempty( loadStopTime )
   loadStopTime = piStarControl.loadStopTime ;
  end
end


% Prepare to write message to the Status Box.
% First set up handles to the Status Text Box in the Startup GUI.
% Search down from the passed figure handle.
if guiEnabled
  statusBoxHandle  = findobj( startPiHandle, 'Tag', 'statusBox' ) ;
  set( statusBoxHandle, 'FontName', 'courier' ) ;
end


% Default to regular .dat files. Dummy flag ? is ignored by PiLine.
% Passing the empty string '' causes a problem with PiLine.
piStarFlagStr = '-?' ;

% Set string for decimation parameters.
if isempty( decimationInterval )
  decimationStr = '-d0' ;  % Zero seconds implies decimation disabled.
else
  decimationStr = [ '-d' num2str( decimationInterval ) ] ;
end

% Set string for elevation mask.
elevationStr = [ '-e' num2str( elevationMask ) ] ;

% Set string for time window parameters. If only one time specified,
% the other is set to -1 = ignore.
if isempty( loadStartTime ) & isempty( loadStopTime )
  timeWindowStr = '-c0,0' ;  % Setting startTime = stopTime disables window.
elseif isempty( loadStartTime )
  timeWindowStr = [ '-c-1,' num2str( loadStopTime ) ] ;
elseif isempty( loadStopTime )
  timeWindowStr = [ '-c' num2str( loadStartTime ) ',-1' ] ;
else
  timeWindowStr = [ '-c' num2str( loadStartTime ) ',' ...
                        num2str( loadStopTime ) ] ;
end

if guiEnabled
% Check if a reference SV has been selected.
  if refSV == -1
    outputRefSVStr = sprintf( 'Ref SV: Highest at start of data file\n\n' ) ;
  elseif refSV == 0
    outputRefSVStr = sprintf( 'Ref SV: Highest at each epoch (can switch)\n\n');
  else
    outputRefSVStr = sprintf( 'Ref SV: %s\n\n', refSVStr ) ;
  end

  if guiData.piLineConfig.loadPiStarFiles  % Load .sim files
    piStarFlagStr = '-p' ;  % Add this flag when calling piLine.
  end
end


%%%%%%%%%% Check if sufficient control parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Check if piStarControl contains sufficient parameters for rkwin.
if piStarControlEnabled & ~piStarControl.piLineValid
  if guiEnabled
    figure( startPiHandle ) ;  % Switch focus to startup window.
    set( statusBoxHandle, 'String', ...
         sprintf( [ 'WARNING!\n' ...
                    'piStar.ini file not contain all PiLine parameters\n' ...
                    'Check for .dat file names and station positions' ] ) ) ;
  end
  piLineFailed = 1 ;  % Returned value.
  return ;
end



if generatePiStar == d_PISTAR_GENERATION
% Check that the data input file (containing ephemerides) can be opened.
% Multi-GNSS simulation uses more than one ephemeris file.

  if 0 && isempty( piStarControl.simEphemerisFileStr )
  % MOVE THIS CHECK TO THE PARSER.
    if guiEnabled
      figure( startPiHandle ) ;  % Switch focus to startup window.
      set( statusBoxHandle, 'String', ...
           sprintf( 'WARNING!\nEphemeris file not specified' ) ) ;
    end
    piLineFailed = 1 ;
    return ;
  end

  if isempty( piStarControl.simEphemerisFileStr )
  % Using precise ephemeris and disabled broadcast ephemeris.
    ephemFileNameStr = '' ;  % piLine will check for empty string.
  else
    % When a file is found, usually details are reported to the status box
    % and focus switched to the start up window. Its neater to keep focus
    % with the simulator GUI (and allow other GUIs to overlay this). In
    % any case, the message gets overwritten immedidately, so set
    % 'verbose' off (pass zero).
    % save and restore current figure.
    ephemFileNameStr = findDataFile( startPiHandle, piStarControl, ...
                                     piStarControl.simEphemerisFileStr{ 1 }, ...
                                     logical( 0 ) ) ;

    if isempty( ephemFileNameStr )
      if guiEnabled
        figure( startPiHandle ) ;  % Switch focus to startup window.
        set( statusBoxHandle, 'String', ...
             sprintf( 'WARNING!\nCannot open file ephemeris data file:\n%s',...
                      piStarControl.simEphemerisFileStr{ 1 } ) ) ;
      end
      piLineFailed = 1 ;
      return ;
    end

    if length( piStarControl.simEphemerisFileStr ) >= 2
    % More than one simulation ephemeris file. Simulating multi-GNSS
    % systems (with an ephemeris file for each GNSS).
    % Current supports dual-GNSS (GPS and Galileo).
      auxEphemFileNameStr = ...
              findDataFile( startPiHandle, piStarControl, ...
                            piStarControl.simEphemerisFileStr{ 2 }, ...
                            logical( 0 ) ) ;

      if isempty( auxEphemFileNameStr )
        if guiEnabled
          figure( startPiHandle ) ;  % Switch focus to startup window.
          set( statusBoxHandle, 'String', ...
               sprintf( [ 'WARNING!\nCannot open file ' ...
                          'auxiliary ephemeris data file:\n%s' ], ...
                        piStarControl.simEphemerisFileStr{ 2 } ) ) ;
        end
        piLineFailed = 1 ;
        return ;
      end
    else  % No Auxiliary ephemeris file (single GNSS simulation only).
      auxEphemFileNameStr = [] ;
    end
  end

elseif piStarControlEnabled

% Check that the data input files can be opened.

  baseFileNameStr = findDataFile( startPiHandle, piStarControl, ...
                                  piStarControl.baseFileNameStr ) ;

  if isempty( baseFileNameStr )
    if guiEnabled
      figure( startPiHandle ) ;  % Switch focus to startup window.
      set( statusBoxHandle, 'String', ...
           sprintf( 'WARNING!\nCannot open file base data or .zip file:\n%s',...
                    piStarControl.baseFileNameStr ) ) ;
    end
    piLineFailed = 1 ;
    return ;
  end

  roverFileNameStr = findDataFile( startPiHandle, piStarControl, ...
                                   piStarControl.roverFileNameStr ) ;
  if isempty( roverFileNameStr )
    if guiEnabled
      figure( startPiHandle ) ;  % Switch focus to startup window.
      set( statusBoxHandle, 'String', ...
           sprintf( 'WARNING!\nCannot open rover data or .zip file:\n%s', ...
                    piStarControl.roverFileNameStr ) ) ;
    end
    piLineFailed = 1 ;
    return ;
  end
end


if piStarControlEnabled
  % Generate the PiLine.ini file. This is a temporary file interface to
  % PiLine which will be replaced by the piLine MatLab API.

  fid = fopen( 'piLine.ini', 'w' ) ;
  if fid == -1
    if guiEnabled
      figure( startPiHandle ) ;  % Switch focus to startup window.
      set( statusBoxHandle, 'String', ...
           sprintf( [ 'WARNING!\n' ...
                      'Cannot open piLine.ini file for write' ] ) ) ;
    end
    piLineFailed = 1 ;  % Returned value.
    return ;
  end

  if generatePiStar == d_PISTAR_GENERATION
  % Calling piLine for simulation observation generation. piLine reads a
  % data file only to obtain ephemerides.

    % Write file name without antenna type. Enclose file name in double
    % quote in case it contains spaces.
    % For single-GNSS simulation (GPS-only), just a base file is given
    % for the ephemeris (the rover file name is empty).
    % For dual-GNSS, base and rover (for auxiliary ephemeris) are given.
    fprintf( fid, '"%s"\r\n', ephemFileNameStr );
    fprintf( fid, '"%s"\r\n', auxEphemFileNameStr );
    fprintf( fid, 'results.out\r\n' ) ;  % Dummy (historic in PiLine).

    fprintf( fid, '0.0\r\n0.0\r\n0.0\r\n' ) ;  % Zeros for dummy vector.
  else
  % Regular use of piLine for diagnostic analysis
    if ~isempty( piStarControl.baseAntennaType ) 
      if piStarControl.baseAntennaType == 255
      % VRS base uses type 255 (NullAntenna) which must be mapped to zero.
        baseAntennaStr = ' 0' ;
      else
        baseAntennaStr = [ ' ' num2str( piStarControl.baseAntennaType ) ]  ;
      end
    else
      baseAntennaStr = '' ;
    end
    if ~isempty( piStarControl.roverAntennaType ) 
      roverAntennaStr = [ ' ' num2str( piStarControl.roverAntennaType ) ]  ;
    else
      roverAntennaStr = '' ;
    end

    % Write file name followed by antenna type (if available). Enclose
    % file name in double quote in case it contains spaces.
    fprintf( fid, '"%s"%s\r\n', baseFileNameStr,  baseAntennaStr  );
    fprintf( fid, '"%s"%s\r\n', roverFileNameStr, roverAntennaStr );
    fprintf( fid, 'results.out\r\n' ) ;  % Dummy (historic in PiLine).

    if piStarControl.baselineVectorValid
      fprintf( fid, '%f\r\n', piStarControl.baselineVectorX ) ;
      fprintf( fid, '%f\r\n', piStarControl.baselineVectorY ) ;
      fprintf( fid, '%f\r\n', piStarControl.baselineVectorZ ) ;
    elseif piStarControl.ecefPositionValid
      fprintf( fid, '0.0\r\n0.0\r\n0.0\r\n' ) ;  % Zeros for vector.
      fprintf( fid, '%f %f %f\r\n', piStarControl.basePositionX, ...
               piStarControl.basePositionY, piStarControl.basePositionZ ) ;
      fprintf( fid, '%f %f %f', piStarControl.roverPositionX, ...
               piStarControl.roverPositionY, piStarControl.roverPositionZ ) ;
    else
    % Use the the computed value translated from the geodetic position.
      fprintf( fid, '0.0\r\n0.0\r\n0.0\r\n' ) ;  % Zeros for vector.
      fprintf( fid, '%f %f %f\r\n', piStarControl.baseXComputed, ...
               piStarControl.baseYComputed, piStarControl.baseZComputed ) ;
      fprintf( fid, '%f %f %f', piStarControl.roverXComputed, ...
               piStarControl.roverYComputed, piStarControl.roverZComputed ) ;
    end
  end

  fclose( fid ) ;
end


%%%%%%%%%% Check passed process type flags and call PiLine %%%%%%%%%%%%%%%%%%%%%
if generatePiStar == d_PISTAR_REGENERATION
% Regenerate observations using collected observations, using new position.

  if ~piStarControl.multipliersValid
    if guiEnabled
      set( statusBoxHandle, 'String', ...
           sprintf( [ 'WARNING!\nFile ' iniFileNameStr ...
                      ' contains invalid multipliers' ] ) ) ;
    end
    return ;
  end

  if guiEnabled
    figure( startPiHandle ) ;  % Switch focus to startup window.
    set( statusBoxHandle, 'String', ...
         'Regenerating PiStar simulation data files...' ) ;
  end
  [ dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy ] = ...
    piLineMex( '-s', ...
             num2str( piStarControl.rangeMultiplierL1, 16 ), ...
             num2str( piStarControl.rangeMultiplierL2, 16 ), ...
             num2str( piStarControl.phaseMultiplierL1, 16 ), ...
             num2str( piStarControl.phaseMultiplierL2, 16 ), '-r0', ...
             decimationStr, elevationStr, timeWindowStr ) ;

elseif generatePiStar == d_PISTAR_GENERATION
% Generate new observations using supplied positions.
  if isempty( simOutputStruct )
    if guiEnabled
      set( statusBoxHandle, 'String', ...
           sprintf( [ 'WARNING!\nScenario must be run before ' ...
                      'observation generation!' ] ) ) ;
    end
    return ;
  end

  if guiEnabled
    % Don't switch focus, as the observations generator will open a new
    % GUI for status info.
    set( statusBoxHandle, 'String', ...
         'Observations generator running...' ) ;
  end
  % Disable start/stop times (not relevant).
  [ dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy ] = ...
    piLineMex( '-z', '-c0,0', d_PISTAR_DECIMATION_STR, simOutputStruct, ...
               simControlStruct, simNetworkStruct ) ;

elseif outputRecord17 & outputResiduals & outputStatRange

  if guiEnabled
    set( statusBoxHandle, 'FontName', 'courier', ...
                          'String', ...
                           [ outputRefSVStr 'Processing all outputs...' ] ) ;
  end

  % Clear any previous load of the arrays.
  phaseDDiffL1 = [] ;
  phaseDDiffL2 = [] ;
  phaseDDiffL2C= [] ;
  phaseDDiffL5 = [] ;
  phaseDDiffGL1_CA  = [] ;
  phaseDDiffGL1_P   = [] ;
  phaseDDiffGL2     = [] ;
  phaseDDiffGalL1   = [] ;
  phaseDDiffGalE5A  = [] ;
  phaseDDiffGalE5B  = [] ;
  phaseDDiffGalE5AB = [] ;
  rangeDDiffL1 = [] ;
  rangeDDiffL2 = [] ;
  rangeDDiffL2C= [] ;
  rangeDDiffL5 = [] ;
  rangeDDiffGL1_CA  = [] ;
  rangeDDiffGL1_P   = [] ;
  rangeDDiffGL2     = [] ;
  rangeDDiffGalL1   = [] ;
  rangeDDiffGalE5A  = [] ;
  rangeDDiffGalE5B  = [] ;
  rangeDDiffGalE5AB = [] ;
  ionoDDiff    = [] ;
  statRangeL1  = [] ;
  statRangeL2  = [] ;
  statRangeL2C = [] ;
  statRangeL5  = [] ;
  rec17DataL1  = [] ;
  rec17DataL2  = [] ;
  rec17DataL2C = [] ;
  rec17DataL5  = [] ;
  datFileNames = [] ;

  % Call the piLine mex file (for MS-windows, piLineMex.dll).
  % Include L5 processing.
  [ phaseDDiffL1, phaseDDiffL2, phaseDDiffL2C, phaseDDiffL5, ...
    phaseDDiffGL1_CA, phaseDDiffGL1_P, phaseDDiffGL2, ...
    phaseDDiffGalL1, phaseDDiffGalE5A, phaseDDiffGalE5B, phaseDDiffGalE5AB, ...
    rangeDDiffL1, rangeDDiffL2, rangeDDiffL2C, rangeDDiffL5, ...
    rangeDDiffGL1_CA, rangeDDiffGL1_P, rangeDDiffGL2, ...
    rangeDDiffGalL1, rangeDDiffGalE5A, rangeDDiffGalE5B, rangeDDiffGalE5AB, ...
    ionoDDiff, statRangeL1, ...  statRangeL2, statRangeL2C, statRangeL5, ...
    rec17DataL1, rec17DataL2, rec17DataL2C, rec17DataL5, piLineParams ] = ...
      piLineMex( '-o340', freqStr, GNSSenableStr, [ '-r' refSVStr ], ...
                 piStarFlagStr,  decimationStr, elevationStr, timeWindowStr ) ;

  % Check that MatLab arrays were transferred. L2 data not required in
  % case using an L1-only receiver. Thus, ionoDDiff is not checked.
  if isempty( rec17DataL1 ) | isempty( statRangeL1 ) | ...
     isempty( phaseDDiffL1 ) | isempty( rangeDDiffL1 )
    piLineFailed = 1 ;
  else
  % Transpose the matrices from the MatLat/FORTRAN standard (# of
  % columns = # of epochs) to a C representation (# of rows = # of
  % epochs).
    phaseDDiffL1  = phaseDDiffL1' ;
    phaseDDiffL2  = phaseDDiffL2' ;
    phaseDDiffL2C = phaseDDiffL2C' ;
    phaseDDiffL5  = phaseDDiffL5' ;
    phaseDDiffGL1_CA = phaseDDiffGL1_CA' ;
    phaseDDiffGL1_P  = phaseDDiffGL1_P' ;
    phaseDDiffGL2    = phaseDDiffGL2' ;
    phaseDDiffGalL1 = phaseDDiffGalL1' ;
    phaseDDiffGalE5A = phaseDDiffGalE5A' ;
    phaseDDiffGalE5B = phaseDDiffGalE5B' ;
    phaseDDiffGalE5AB = phaseDDiffGalE5B' ;
    rangeDDiffL1  = rangeDDiffL1' ;
    rangeDDiffL2  = rangeDDiffL2' ;
    rangeDDiffL2C = rangeDDiffL2C' ;
    rangeDDiffL5  = rangeDDiffL5' ;
    rangeDDiffGL1_CA = rangeDDiffGL1_CA' ;
    rangeDDiffGL1_P  = rangeDDiffGL1_P' ;
    rangeDDiffGL2    = rangeDDiffGL2' ;
    rangeDDiffGalL1 = rangeDDiffGalL1' ;
    rangeDDiffGalE5A = rangeDDiffGalE5A' ;
    rangeDDiffGalE5B = rangeDDiffGalE5B' ;
    rangeDDiffGalE5AB = rangeDDiffGalE5AB' ;
    ionoDDiff     = ionoDDiff' ;
    statRangeL1   = statRangeL1' ;
    statRangeL2   = statRangeL2' ;
    statRangeL2C  = statRangeL2C' ;
    statRangeL5   = statRangeL5' ;
    rec17DataL1   = rec17DataL1' ;
    rec17DataL2   = rec17DataL2' ;
    rec17DataL2C  = rec17DataL2C' ;
    rec17DataL5   = rec17DataL5' ;

    % Include the clock bias to provide the GPS time-tag. This is required
    % for the cycle-slip detection routines, etc.
    % Note: clock offest is stored in msec (hence, / 1000 to convert to
    % seconds).
    rec17DataL1( :, 1 ) = ( rec17DataL1( :, 1 ) - rec17DataL1( :, 2) / 1000 ) ;

    if ~isempty( rec17DataL2 ) % In case data is from an L1-only receiver.
      rec17DataL2( :, 1 ) = ( rec17DataL2( :, 1 ) - rec17DataL2( :, 2) / 1000 );
    end

    if ~isempty( rec17DataL5 ) % In case no L5 data.
      rec17DataL5( :, 1 ) = ( rec17DataL5( :, 1 ) - rec17DataL5( :, 2) / 1000 );
    end
  end

elseif outputRecord17
  outputRefSVStr = '' ;  % Suppress display in message below.

  if guiEnabled
    set( statusBoxHandle, 'FontName', 'courier', ...
                          'String', ...
                          'Transferring record 17 data...' ) ; ;
  end
  rec17DataL1  = [] ;
  rec17DataL2  = [] ;
  rec17DataL2C = [] ;
  rec17DataL5  = [] ;
  datFileNames = [] ;

  % Does not require record 11 (position) in the .dat file.
  % Parameters that are not loaded by PiLab have a dummy variable passed
  % so the subsequent arguments are in the correct position.
  [ dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, rec17DataL1, rec17DataL2, rec17DataL2C, ...
    rec17DataL5, piLineParams ] = ...
      piLineMex( '-o16', freqStr, GNSSenableStr, '-r0', piStarFlagStr, ...
                 decimationStr, elevationStr, timeWindowStr ) ;

  % Check that MatLab arrays were transferred. L2 data not required in
  % case using an L1-only receiver.
  if isempty( rec17DataL1 )
    piLineFailed = 1 ;
  else
    rec17DataL1 = rec17DataL1' ;
    % See example above for details.
    rec17DataL1( :, 1 ) = ( rec17DataL1( :, 1 ) - rec17DataL1( :, 2) / 1000 ) ;

    if ~isempty( rec17DataL2 ) % In case data is from an L1-only receiver.
      rec17DataL2 = rec17DataL2' ;
      rec17DataL2( :, 1 ) = ( rec17DataL2( :, 1 ) - rec17DataL2( :, 2) / 1000 );
    end

    if ~isempty( rec17DataL5 ) % In case data is from an L1-only receiver.
      rec17DataL5 = rec17DataL5' ;
      rec17DataL5( :, 1 ) = ( rec17DataL5( :, 1 ) - rec17DataL5( :, 2) / 1000 );
    end
  end

elseif outputResiduals
  if guiEnabled
    set( statusBoxHandle, 'FontName', 'courier', ...
                          'String', ...
                          [ outputRefSVStr ...
                            'Processing range/phase/iono residuals...' ] ) ;
  end
  phaseDDiffL1  = [] ;
  phaseDDiffL2  = [] ;
  phaseDDiffL2C = [] ;
  phaseDDiffL5  = [] ;
  phaseDDiffGL1_CA = [] ;
  phaseDDiffGL1_P  = [] ;
  phaseDDiffGL2    = [] ;
  rangeDDiffL1  = [] ;
  rangeDDiffL2  = [] ;
  rangeDDiffL2C = [] ;
  rangeDDiffL5  = [] ;
  rangeDDiffGL1_CA = [] ;
  rangeDDiffGL1_P  = [] ;
  rangeDDiffGL2    = [] ;
  ionoDDiff     = [] ;
  datFileNames  = [] ;

  [ phaseDDiffL1, phaseDDiffL2, phaseDDiffL2C, phaseDDiffL5, ...
    phaseDDiffGL1_CA, phaseDDiffGL1_P, phaseDDiffGL2, ...
    phaseDDiffGalL1, phaseDDiffGalE5A, phaseDDiffGalE5B, phaseDDiffGalE5AB, ...
    rangeDDiffL1, rangeDDiffL2, rangeDDiffL2C, rangeDDiffL5, ...
    rangeDDiffGL1_CA, rangeDDiffGL1_P, rangeDDiffGL2, ...
    rangeDDiffGalL1, rangeDDiffGalE5A, rangeDDiffGalE5B, rangeDDiffGalE5AB, ...
    ionoDDiff, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, piLineParams ] = ...
    piLineMex( '-o320', freqStr, GNSSenableStr, [ '-r' refSVStr ], ...
               piStarFlagStr, decimationStr, elevationStr, timeWindowStr ) ;

  % Test to extract the command line for running a console .exe version
  % fprintf( [ '-o320' freqStr GNSSenableStr [ '-r' refSVStr ] piStarFlagStr ...
  %            decimationStr elevationStr timeWindowStr ] ) ;

  % Check that MatLab arrays were transferred. L2 data not required in
  % case using an L1-only receiver. Thus, ionoDDiff is not checked.
  if isempty( phaseDDiffL1 ) | isempty( rangeDDiffL1 )
    piLineFailed = 1 ;
  else
  % Transpose the matrices from the MatLat/FORTRAN standard (# of
  % columns = # of epochs) to a C representation (# of rows = # of
  % epochs).
    phaseDDiffL1 = phaseDDiffL1' ;
    phaseDDiffL2 = phaseDDiffL2' ;
    phaseDDiffL2C = phaseDDiffL2C' ;
    phaseDDiffL5 = phaseDDiffL5' ;
    phaseDDiffGL1_CA = phaseDDiffGL1_CA' ;
    phaseDDiffGL1_P  = phaseDDiffGL1_P' ;
    phaseDDiffGL2    = phaseDDiffGL2' ;
    phaseDDiffGalL1 = phaseDDiffGalL1' ;
    phaseDDiffGalE5A = phaseDDiffGalE5A' ;
    phaseDDiffGalE5B = phaseDDiffGalE5B' ;
    phaseDDiffGalE5AB = phaseDDiffGalE5B' ;
    rangeDDiffL1 = rangeDDiffL1' ;
    rangeDDiffL2 = rangeDDiffL2' ;
    rangeDDiffL2C = rangeDDiffL2C' ;
    rangeDDiffL5 = rangeDDiffL5' ;
    rangeDDiffGL1_CA = rangeDDiffGL1_CA' ;
    rangeDDiffGL1_P  = rangeDDiffGL1_P' ;
    rangeDDiffGL2    = rangeDDiffGL2' ;
    rangeDDiffGalL1 = rangeDDiffGalL1' ;
    rangeDDiffGalE5A = rangeDDiffGalE5A' ;
    rangeDDiffGalE5B = rangeDDiffGalE5B' ;
    rangeDDiffGalE5AB = rangeDDiffGalE5AB' ;
    ionoDDiff    = ionoDDiff' ;
  end

elseif outputStatRange
  outputRefSVStr = '' ;  % Suppress display in message below.

  if guiEnabled
    set( statusBoxHandle, 'FontName', 'courier', ...
                          'String', ...
                          'Processing stationary range output...' ) ;
  end
  statRangeL1  = [] ;
  statRangeL2  = [] ;
  statRangeL2C = [] ;
  statRangeL5  = [] ;
  datFileNames = [] ;

  [ dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    dummy, ...
    dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, ...
    statRangeL1, statRangeL2, statRangeL2C, statRangeL5, dummy, dummy, ...
    dummy, dummy, piLineParams ] = ...
    piLineMex( '-o4', freqStr, '-r0', piStarFlagStr, decimationStr, ...
               elevationStr, timeWindowStr ) ;

  % Check that MatLab arrays were transferred. L2 data not required in
  % case using an L1-only receiver.
  if isempty( statRangeL1 )
    piLineFailed = 1 ;
  else
    statRangeL1 = statRangeL1' ;
    statRangeL2 = statRangeL2' ;
    statRangeL2C = statRangeL2C' ;
    statRangeL5 = statRangeL5' ;
  end
else
  piLineFailed = 2 ;  % Should never occur.
end

if ~piLineFailed
  if generatePiStar
    refFileNameStr   = 'dummy reference' ;
    roverFileNameStr = 'dummy rover' ;

  else
    % Transfer PiLine processing parameters and input file names.

    piLineOutput.refSV = piLineParams.refSV ;
    if piLineOutput.refSV == 0     % Set to zero when not specified.
      piLineOutput.refSV = NaN ;  % Indicates not available.
    end

    datFileNames.reference = piLineParams.stn1FileName ;
    datFileNames.rover =     piLineParams.stn2FileName ;

    % File names containing the special char '_' will have the following
    % char displayed as a subscript (if written to a MatLab plot). To
    % prevent this, each '_' must be preceeded by a '\'
    % However, an original copy must be saved when using sprintf below.
    [path, name, ext ] = fileparts( datFileNames.rover ) ;
    roverFileNameStr = [ name ext ] ;
    [path, name, ext ] = fileparts( datFileNames.reference ) ;
    refFileNameStr   = [ name ext ] ;

    % TEMPORARY FIX.
    % If files were retrieved from the cache, they will have very long
    % names constructed from the full path. This must be reduced in size
    % to fit the plots.
    if strcmp( 'tmp_', refFileNameStr( 1:4 ) ) & ...
       length( refFileNameStr > 20 )  % Only include last 20 chars of name.
      refFileNameStr = [ '...' refFileNameStr( end-19:end ) ] ;
    end
    if strcmp( 'tmp_', roverFileNameStr( 1:4 ) ) & ...
       length( roverFileNameStr > 20 )  % Only include last 20 chars of name.
      roverFileNameStr = [ '...' roverFileNameStr( end-19:end ) ] ;
    end

    datFileNames.reference = strrep( refFileNameStr, '_', '\_' ) ;
    datFileNames.rover =     strrep( roverFileNameStr,     '_', '\_' ) ;
  end
end

% Necessary to clear function as it appears that any previous call to
% this will not complete the dynamic memory free, and causes a crash
% next time piLineMex is run.
%clear piLineMex ;

% PiLine processing finished.

if guiEnabled 
  if piLineFailed == 2  % Called with no options set. Should never occur.
    set( statusBoxHandle, 'String', ...
                          '!! Attempted to call PiLine with no options!!' ) ;
  elseif piLineFailed
    set( statusBoxHandle, 'String', ...
         sprintf( [ '!!PiLine processing failed!!\n\n' ...
                    'Check error message from PiLine' ] ) ) ;

  elseif generatePiStar == d_PISTAR_REGENERATION
    set( statusBoxHandle, 'String', ...
         sprintf( [ 'Observations regeneration complete\n\n' ...
                    'Phase Multipliers: %5.2f [L1] %5.2f [L2]\n' ...) ;
                    'Range Multipliers: %5.2f [L1] %5.2f [L2]' ], ...
                    piStarControl.phaseMultiplierL1, ...
                    piStarControl.phaseMultiplierL2, ...
                    piStarControl.rangeMultiplierL1, ...
                    piStarControl.rangeMultiplierL2 ) ) ;
  elseif generatePiStar == d_PISTAR_GENERATION
    % No additional display. Leave earlier '...running...' display until
    % the observations generations thread is exited.
  else
    % Need sprintf to format \n
    if guiData.piLineConfig.loadPiStarFiles  % Loaded .sim files
      fileTypeStr = ' [used PiStar data files]' ;
    else
      fileTypeStr = '' ;
    end
    set( statusBoxHandle, 'String', ...
         sprintf( [ outputRefSVStr 'PiLine processing complete' ...
                    fileTypeStr '\n\n' ...
                      'Base  (station 1) file name: %s' ...
                    '\nRover (station 2) file name: %s' ...
                    '\nBase  antenna type: %d ' ...
                    '\nRover antenna type: %d ' ...
                  ], refFileNameStr, roverFileNameStr, ...
                     piLineParams.antennaTypeBase, ...
                     piLineParams.antennaTypeRover ) ) ;
  end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% $Log: runPiLine.m,v $
% Revision 1.8  2008/08/04 21:57:35  vnadkar
% Copy over version 1.40 of runPiLine.m from PiLab to support new ouput fields for Galileo.
%
% Revision 1.40  2008/06/19 07:40:35  timo
% Disable Galileo processing in call to piLineMex.dll.
%
% Revision 1.39  2008/05/14 16:09:54  timo
% Remove diag output giving string sent to piLabMex.dll.
%
% Revision 1.38  2008/04/28 20:44:31  timo
% Updates to support Galileo. Must use a new piLineMex.dll.
%
% Revision 1.37  2007/10/30 12:12:59  timo
% Add support for dual-GNSS PiStar simulation.
%
% Revision 1.36  2006/09/26 15:21:24  timo
% Correct typo
%
% Revision 1.35  2006/07/21 13:26:08  timo
% Map base NullAntenna type 255 to zero for PiLine.
%
% Revision 1.34  2006/06/09 15:59:36  timo
% Test code to extract method of running piLine.exe from the
% console. Provides command line parameters.
%
% Revision 1.33  2005/05/15 20:09:20  timo
% Updates to support L2C, L5 and W plots.
%
% Revision 1.32  2005/04/21 17:13:08  timo
% Fix typo for new W matrices transfer from PiLine.
%
% Revision 1.31  2005/04/19 08:14:02  timo
% Fix cut and paste errors for Glonass PiLine matrices.
%
% Revision 1.30  2005/04/05 10:25:02  timo
% Updates for W data double-diff residuals.
%
% Revision 1.29  2004/11/02 10:05:41  timo
% Updates to support precise ephemeris.
%
% Revision 1.28  2004/09/15 13:54:05  timo
% Update to Matlab 14. Rename num2Str() to num2str().
%
% Revision 1.27  2004/08/17 16:32:43  timo
% Fix piStarControlEnabled flag which was not being set after
% reading the piStar.ini file
%
% Revision 1.26  2004/07/14 09:37:36  timo
% Fix error in use of nargin (input arguments).
% Remove redundant PiStar parameters since updates to network simulation.
%
% Revision 1.25  2004/06/22 08:52:30  timo
% Add elevation mask parameter for all double-diff processing.
% The PiLab mask now controls PiLine and not just the PiLab
% plots in MatLab.
%
% Revision 1.24  2004/03/09 14:32:53  timo
% Updates to PiStar for network simulation.
%
% Revision 1.23  2004/02/12 13:41:49  timo
% On going updates for network simulation.
%
% Revision 1.22  2004/01/15 18:19:19  timo
% Updates to support observables generator as a separate
% thread in the piLineMex.dll.
%
% Revision 1.21  2003/11/18 09:51:44  timo
% Updates for L5 support and selection of output file type.
%
% Revision 1.20  2003/10/07 13:18:51  timo
% Updates for L2C test mode.
%
% Revision 1.19  2003/10/02 16:52:11  timo
% Updates to support L5.
%
% Revision 1.18  2003/10/01 16:38:04  timo
% Updates for L5 PiLine processing.
%
% Revision 1.17  2003/09/26 00:44:00  timo
% Update comment for input parameters.
%
% Revision 1.16  2003/05/20 13:45:20  timo
% Updates for PiStar simulator.
%
% Revision 1.15  2003/01/08 12:03:06  timo
% Updates to start/stop times. Only one needs to be specified.
%
% Revision 1.14  2003/01/03 11:30:33  timo
% Add support for PiLine start/stop times and decimation.
%
% Revision 1.13  2002/08/22 14:04:17  timo
% Temporary fixes to deal with long file names from the cache.
%
% Revision 1.12  2002/07/29 14:27:54  timo
% Further updates to support databases.
%
% Revision 1.11  2002/01/17 16:12:50  timo
% Correct message string, 'piLine.ini' should read 'piStar.ini'.
%
% Revision 1.10  2001/11/08 09:34:36  timo
% Fix problem with L1 only data (incorrectly checking for presence of
% iono residuals).
%
% Revision 1.9  2001/10/02 09:13:49  timo
% Updates for V3.12
%
% Revision 1.8  2001/09/13 16:28:46  timo
% Add support for using PiStar.ini file.
%
% Revision 1.7  2001/07/12 10:55:09  timo
% Updates for V3.10 beta release 12 July 2001.
%
% Revision 1.6  2001/06/05 10:42:19  timo
% Updates to integrate PiLine and PiLab using the MatLab API.
% PiLine is now a .dll called from PiLab.
%
% Revision 1.5  2001/04/24 11:03:46  timo
% Updates for 25-Apr-01 V3 beta release.
%
% Revision 1.4  2001/04/11 14:12:31  timo
% Updates for 11-Apr-01 V3 beta release.
%
% Revision 1.3  2001/03/15 17:36:16  timo
% Add instructions to GUI on how to run PiLine.
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
