% Written by Daniel Shima, Vanderbilt Vision Research Center, 13 July 2004.

% Make sure you have installed Psychtoolbox Version 2.52 (12 August 2002)
% or later as the PsychSerial command below needs to read binary and includes
% the expirationSecs parameter if you end up using PsychSerial('Read') as well
% PsychSerial('Write').

% This code shows how to construct and send serial commands with the necessary
% character headers from Matlab on Mac to ViewPoint on Mac or Windows using
% the PsychSerial command in a very basic way.

% The different types of serial commands are described in the ViewPoint documentation,
% but not precisely how to construct them in Matlab, so I shared this code with
% the Psychtoolbox group.  It is nothing more than an example of using the
% Psychserial command for this particular application.

% The ViewPoint software has its own menu commands for opening a serial port with
% particular settings.

% In Matlab, you need to open your serial port and then, for each command you wish
% to send to ViewPoint, construct a header that is:
% ['V' 'P' char(headerserialtagvalue) char(length(packettext))]
% followed by the characters forming the command.  See code below.

% I was using a Belkin USB-to-serial adapter and, after reviewing PsychSerialTest.m,
% found it necessary to set the outCTSEnable of the serial port to zero in addition
% to the other communication parameters.  Otherwise, the serial line got stuck a lot.

% Once you establish serial communication you need to write Matlab code to
% properly send and maybe receive ViewPoint instructions data and with the
% necessary header types and length.  The idea is that the PsychSerial
% commands get added to your normal Psychtoolbox visual stimulus/response
% collection study as an enhancement that allows you to collect eye data
% from ViewPoint.

% The code below does not show how to use the PsychSerial('Read') command to read
% eye data from ViewPoint to Matlab, only how to send commands from Matlab to ViewPoint
% using PsychSerial('Write'), but once you have a little success with the serial
% connection, you should be able to figure out how to read ViewPoint data in Matlab.
% As I recall, ViewPoint eye data arrives with the same header logic as the
% commands below, so you need to write Matlab code to parse through the arriving packets.

% But I recommend using Matlab only to send short instructions to ViewPoint
% when to start and stop collecting data, or inserting text in the eye data
% at critical moments, and saving all data in files on the ViewPoint computer.
% In that sense, design a study in which the Psychtoolbox Matlab visual stimulus
% and experimental control code is the master and the ViewPoint eye data collection
% software is the slave.

% (Repeating,) in a two-computer situation, I am encouraging you to use Matlab as
% the master and ViewPoint as the slave, where Matlab sends little serial instructions
% to ViewPoint at critical times to open a new data file, to start or stop saving data,
% or to insert helpful text as a time stamp in the data file, and ViewPoint never sends
% anything the other way over to Matlab.  All data is collected on the ViewPoint computer
% for analysis later.

% If your study involves something like waiting for fixation, where Matlab would need
% to know when a subject is fixated in order to continue the trial, I am afraid I have
% not tackled that with ViewPoint.  You will have to experiment with setting ViewPoint
% to send data serially and using the Pschyserial('Read') command and your own code to
% collect and analyze it.  Or maybe Karl Arrigton at ViewPoint has developed triggers
% that can be sent serially when events like fixation occur.  He was my source of help
% when I was going through it the first time.

% I hope I remember these correctly.  Karl Arrington could certainly verify.
% The four dataFile Header-Serial-Tag-Value-11 COMMAND_LINE commands I know are:
% dataFile_NewUnique
% dataFile_Pause
% dataFile_Resume
% dataFile_Close
% And then there is Header-Serial-Tag-Value-12 DATAFILE_INSERT commands for inserting text into active recording data files.

% So the code below should:
%  1. Open the serial port and set necessary parameters.
%  2. Open a unique data file with a numeric name on your ViewPoint computer and start recording.
%  3. Wait for 1 second.
%  4. Pause recording.
%  5. Wait for 1 second.
%  6. Resume recoding.
%  7. Wait for 1 second.
%  8. Insert a string into the data file.
%  9. Wait for 1 second.
% 10. Close the data file.
% 11. Close the serial port.

% When the program finishes, you should see a new file on your ViewPoint computer
% with a unique numeric name that has data with time stamps that follow the pattern
% of the Matlab serial commands.

clear all;

% Open serial port at baudRate 57600, your inputDriverName and outputDriverName may be something other that .Bin and .Bout.
serialportname = PsychSerial('Open','.Bin','.Bout',57600);
% Read current serial port parameters into serialportparams structure.
serialportparams = PsychSerial('Params',serialportname);
% Adjust elements of serialportparams structure to whatever you need.
% In this case, reset the hardware before anything else, then set baud rate to 57600 again, 8 NONE 1,
% and turn off Clear-To-Send flow control in case nothing connected to Mac so it does not attempt to write and hang up forever.
serialportparams.hardwareReset = 1;
serialportparams.baudRate = 57600;
serialportparams.dataBits = 8;
serialportparams.stopBits = 1;
serialportparams.parity = 'none';
serialportparams.outCTSEnable = 0; % From PsychSerialTest.m, keeps Belkin adapter from hanging up.
% Apply serialportparams to open serial port.
PsychSerial('Params',serialportname,serialportparams);
disp('Serial port opened.');

packettext = 'dataFile_NewUnique';
headerserialtagvalue = 11;
header = ['V' 'P' char(headerserialtagvalue) char(length(packettext))];
serialoutdata = [header packettext];
PsychSerial('Write',serialportname,serialoutdata);
disp('Open unique data file COMMAND_LINE command sent to ViewPoint.');

WaitSecs(1);

packettext = 'dataFile_Pause';
headerserialtagvalue = 11;
header = ['V' 'P' char(headerserialtagvalue) char(length(packettext))];
serialoutdata = [header packettext];
PsychSerial('Write',serialportname,serialoutdata);
disp('Pause recording to unique data file COMMAND_LINE command sent to ViewPoint.');

WaitSecs(1);

packettext = 'dataFile_Resume';
headerserialtagvalue = 11;
header = ['V' 'P' char(headerserialtagvalue) char(length(packettext))];
serialoutdata = [header packettext];
PsychSerial('Write',serialportname,serialoutdata);
disp('Resume recording to unique data file COMMAND_LINE command sent to ViewPoint.');

WaitSecs(1);

packettext = 'This is the insert text string sent from Matlab.';
headerserialtagvalue = 12;
header = ['V' 'P' char(headerserialtagvalue) char(length(packettext))];
serialoutdata = [header packettext];
PsychSerial('Write',serialportname,serialoutdata);
disp('Insert text string DATAFILE_INSERT command sent to ViewPoint.');

WaitSecs(1);

packettext = 'dataFile_Close';
headerserialtagvalue = 11;
header = ['V' 'P' char(headerserialtagvalue) char(length(packettext))];
serialoutdata = [header packettext];
PsychSerial('Write',serialportname,serialoutdata);
disp('Close unique data file COMMAND_LINE command sent to ViewPoint.');

PsychSerial('Close',serialportname)
disp('Serial port closed.');
