function XYZ = CRSColorMeasXYZ
% XYZ = CRSColorMeasXYZ
%
% Measure XYZ using CRS Colorimeter.
%
% NOTE: Under some circumstances, it might be possible
% to squeeze a little more accuracy out of the instrument
% by lowering integration time and making a low light level
% measurement.  This depends on what the instrument can
% return for a low-light level measurement when one value
% exceeds 99.99.
%
% 2/2/03  dhb  Wrote it.
% 2/21/03 pw	 Check for out of bounds return (>= 999.99)
% 2/24/03 pw   function measXYZ
% 2/24/03 pw   function CRSColorParse.
% 2/25/03 pw, etc  Minor clean up.
% 2/26/03 everyone Handle empty string for LLM case.
%                  Change ' ' to '0' in response string.
% 2/27/03 eh, jb added call to zero calibration
% 3/7/03  jb moved call CRSColorZeroCal from CRSColorMeasXYZ to CRSColorTest

global crsColorInfo

% Default command to device is 'MES'
command = 'MES';

% Call MeasXYZ to operate the device and return measurement
response = CRSColorRawXYZ(command);

% Parse the response
XYZ = CRSColorParse(command,response);

% If X, Y, or Z is below 10 (arbitrary 'low' value), then remeasure
% using the low luminance command and substitute this measurement into the 
% low X Y or Z.
% Set thresholds 
lowLevel = 15;
highLevel = 90;
isLow = (XYZ < lowLevel);
isHigh = (XYZ > highLevel);

if (any(isLow) & ~any(isHigh))	
	% If any XYZ measurement falls below threshold, remeasure with 
	% low luminance comand
	% Call MeasXYZ, command = 'LLM'
	command = 'LLM';
	response = CRSColorRawXYZ(command);
	
	% Parse the response
	XYZLow = CRSColorParse(command,response);
	
	% Then substitute in the right values
	subIndex = (XYZ < highLevel);
	XYZ(subIndex) = XYZLow(subIndex);
end
return


function XYZ = CRSColorParse(command,response)
% XYZ = CRSColorParse(command,response)
%
% Parse the device response, cutting out 'OK00', and separating
% RGB values into X Y and Z.  OOB X,Y,Z change based on command sent to device.
%
% 2/24/03  ptw  Pulled out and made a separate routine.

switch command
	case 'MES'
		highX = '999.99';
		highY = '999.99';
		highZ = '999.99';
		empty = '   .  ';
	case 'LLM'
		highX = '99.999';
		highY = '99.999';
		highZ = '99.999';
		empty = '  .   ';
	otherwise
		error('Parse impossible- bad command sent to device\n');
end

% Change spaces to zeros in numeric responses
index = find(response == ' ');
if (~isempty(index))
	response(index) = '0';
end
	
if (strncmp(response,'OK',2))
	% Get numbers out of the string
	%fprintf('Response was: %s\n',response);
	
	% Check X for empty or 999.99/99.999 response 
	if(strcmp(response(6:11),empty))
		X = 0;
	elseif(strcmp(response(6:11),highX))
		X = NaN;
	else
		X = str2num(response(6:11));
	end
	
	% Check Y for empty or 999.99 response
	if (strcmp(response(13:18),empty))
		Y = 0;
	elseif(strcmp(response(13:18),highY))
		Y = NaN;
	else
		Y = str2num(response(13:18));
	end
	
	% Check Z for empty or 999.99 response  
	if (strcmp(response(20:25),empty))
		Z = 0;
	elseif(strcmp(response(20:25),highZ))
		Z = NaN;
	else
		Z = str2num(response(20:25));
	end
	XYZ = [X Y Z]';
	
elseif (strncmp(response,'ER',2))
	errorCode = str2num(response(3:4));
	switch (errorCode)
		case 18,
			error('EPROM error in CRS meter.  Uh Oh!');
		case 11,
			error('Zero calibration error in CRS meter.  Recalibrate');
		case 13,
			error('Too much light for CRS meter to measure.  Change integration time.');
		case 30,
			error('Vertical scanning frequency error in CRS meter.');
		otherwise,
			error(sprintf('Unknown error code from CRS meter: %d\n',errorCode));
	end
else
	error(sprintf('Weird response from CRS color meter: %s\n',response));
end
return


function response = CRSColorRawXYZ(command)
% response = CRSColorRawXYZ(command)
%
% This will operate and return response from device
% Difference between MES and LLM is the command, output variable can
% be the same.

global crsColorInfo

cmd = '                                ';

switch command
	case 'MES'
		cmd(1:3) = 'MES';
	case 'LLM'
		cmd(1:3) = 'LLM';
	otherwise
		error('No command to device sent\n');
end

% Write a command and get response

cmd(4) = char(10);
PSYCHSERIAL('Write',crsColorInfo,cmd);

% Read response
response = PSYCHSERIAL('ReadRaw',crsColorInfo,32);
if (isempty(response))
	error('No response from the CRS color meter');
end
return
