Jump to content

User Tutorial:BCI2000Remote: Difference between revisions

From BCI2000 Wiki
Swiftj (talk | contribs)
Swiftj (talk | contribs)
 
(6 intermediate revisions by 3 users not shown)
Line 7: Line 7:
==Python Tutorial==
==Python Tutorial==
<ol>
<ol>
<li>Find your Python folder. If you have an existing Python environment with your code find it using the Sys Library like this:  
<li>Find your Python folder. If you have an existing Python environment with your code find it using the Sys Library like this:
<pre>
<syntaxhighlight lang="python">
import sys
import sys


locate_python = sys.exec_prefix
locate_python = sys.exec_prefix
print(locate_python)
print(locate_python)
</pre>
</syntaxhighlight>
 
</li>
</li>
<li>
<li>
Locate your BCI2000Remote.py file which should have compiled into your prog folder.  
Locate your BCI2000Remote.py file which should have compiled into your prog folder.  
Find where in your Python code you wish to integrate BCI2000. In this example I will show the minimum requirements for integration with BCI2000:
Find where in your Python code you wish to integrate BCI2000. In this example I will show the minimum requirements for integration with BCI2000:
<pre>
 
import sys
<syntaxhighlight lang="python">
# Set BCI2000 path
import sys, time
sys.path.append('C:\\BCI2000.x64\\prog')
sys.path.append('C:\\BCI2000.x64\\prog')
# BCI2000 setup
import BCI2000Remote
import BCI2000Remote
bci = BCI2000Remote.BCI2000Remote()
bci = BCI2000Remote.BCI2000Remote()
print('Operator path:', bci.OperatorPath)
bci.WindowVisible = True
bci.WindowVisible = True
bci.WindowTitle = 'Python controlled'
bci.WindowTitle   = 'BCI2000 Remote Python'
bci.SubjectID = 'pysub'
bci.Connect()
bci.Connect()
bci.Execute('cd ${BCI2000LAUNCHDIR}')
bci.Execute('cd ${BCI2000LAUNCHDIR}')
bci.Execute('ADD EVENT score 16 0')
bci.Execute('ADD EVENT Square 2 0')
bci.StartupModules(('SignalGenerator', 'DummySignalprocessing', 'DummyApplication'))
bci.StartupModules(('SignalGenerator', 'DummySignalprocessing', 'DummyApplication'))
bci.Execute('Wait for Connected')
bci.Execute('Wait for Connected')
bci.LoadParametersRemote('../parms/fragments/amplifiers/SignalGenerator.prm')
bci.LoadParametersRemote('..\\parms\\fragments\\amplifiers\\SignalGenerator.prm')
bci.SetConfig()
bci.Execute('Wait for Running')
</pre>
bci.Execute('Set event Square 1')
</syntaxhighlight>
 
Here is how you import BCI2000Remote:
Here is how you import BCI2000Remote:
<br>
<br>
Line 79: Line 86:


<gallery mode="packed" widths=300px heights=300px>
<gallery mode="packed" widths=300px heights=300px>
File:BCIRemote_55.png
File:BCIRemote_6.png
</gallery>
</gallery>


Line 87: Line 94:


<gallery mode="packed" widths=300px heights=300px>
<gallery mode="packed" widths=300px heights=300px>
File:BCIRemote_6.png
File:BCIRemote_666.png
</gallery>
</gallery>


Line 96: Line 103:


<gallery mode="packed" widths=300px heights=300px>
<gallery mode="packed" widths=300px heights=300px>
File:BCIRemote_6.png
File:BCIRemote_8.png
</gallery>
</gallery>


Line 167: Line 174:
</i>
</i>
<li>
<li>
Make sure that you include all of your dependencies including BCI2000Remote.h  
Make sure that you include all of your dependencies including BCI2000Remote.h
<pre>
 
<syntaxhighlight lang="cpp">
#include "BCI2000Remote.h"
#include "BCI2000Remote.h"
#include <string>
#include <string>
#include <vector>
#include <vector>
#include <iostream>
#include <iostream>
</pre>
</syntaxhighlight>
 
</li>
</li>
<li>
<li>
Next, instantiate the BCI2000Remote object
Next, instantiate the BCI2000Remote object
<pre>
 
<syntaxhighlight lang="cpp">
int main( int argc, char* argv[] )
int main( int argc, char* argv[] )
{
{
Line 193: Line 203:
     return -1;
     return -1;
   }
   }
</pre>
</syntaxhighlight>
 
</li>
</li>
<li>
<li>
Specify your startup modules and any flags you wish to start them with
Specify your startup modules and any flags you wish to start them with
<pre>
 
<syntaxhighlight lang="cpp">
   // Startup modules
   // Startup modules
   const char* modules[] = { "SignalGenerator --LogMouse=1", "ARSignalProcessing", "CursorTask" };
   std::vector<std::string> modules{ "SignalGenerator --LogMouse=1", "ARSignalProcessing", "CursorTask" };
  std::vector<std::string> vModules( &modules[0], &modules[0] + sizeof( modules ) / sizeof( *modules ) );
   if( !bci.StartupModules( modules ) )
   if( !bci.StartupModules( vModules ) )
   {
   {
     std::cerr << bci.Result();
     std::cerr << bci.Result();
     return -1;
     return -1;
   }
   }
</pre>
</syntaxhighlight>
</li>
</li>
<li>
<li>
Load any parameter files and set subject information
Load any parameter files and set subject information
<pre>
 
<syntaxhighlight lang="cpp">
bci.LoadParametersRemote( "../parms/examples/CursorTask_SignalGenerator.prm" );
bci.LoadParametersRemote( "../parms/examples/CursorTask_SignalGenerator.prm" );
   bci.SubjectID( "SUB" );
   bci.SubjectID( "SUB" );
Line 219: Line 231:
     return -1;
     return -1;
   }
   }
</pre>
</syntaxhighlight>
</li>
</li>
</li>
</li>
<li>
<li>
And here we just have BCI2000 send us back a feedback signal:
And here we just have BCI2000 send us back a feedback signal:
<pre>
<syntaxhighlight lang="cpp">
   std::string state;
   std::string state;
   while( bci.GetSystemState( state ) && state == "Running" )
   while( bci.GetSystemState( state ) && state == "Running" )
Line 236: Line 248:
   return 0;
   return 0;
}
}
</pre>
</syntaxhighlight>
</li>
</li>
<li>
<li>
Now that you've added those components to your code all you have to do is compile and run it. You should see the BCI2000 operator along with the system log, source watcher, and the timing window.
Now that you've added those components to your code all you have to do is compile and run it. You should see the BCI2000 operator along with the system log, source watcher, and the timing window.
<b>Note:</b> Be sure to compile this in your prog folder. This can be done by navigating again to Configuration Properties -> General, and changing the Output Directory to the path of the BCI2000 prog folder.
<b>Note:</b> Be sure to compile this in your prog folder. This can be done by navigating again to Configuration Properties -> General, and changing the Output Directory to the path of the BCI2000 prog folder.
[[File:BCIRemote_7.jpg]]
</li>
</li>
</ol>
</ol>
<pre>
<syntaxhighlight lang="cpp">
#include "BCI2000Remote.h"
#include "BCI2000Remote.h"
#include <string>
#include <string>
Line 266: Line 277:
   }
   }
   // Startup modules
   // Startup modules
   const char* modules[] = { "SignalGenerator --LogMouse=1", "ARSignalProcessing", "CursorTask" };
   std::vector<std::string> modules{ "SignalGenerator --LogMouse=1", "ARSignalProcessing", "CursorTask" };
  std::vector<std::string> vModules( &modules[0], &modules[0] + sizeof( modules ) / sizeof( *modules ) );
   if( !bci.StartupModules( modules ) )
   if( !bci.StartupModules( vModules ) )
   {
   {
     std::cerr << bci.Result();
     std::cerr << bci.Result();
Line 294: Line 304:
   return 0;
   return 0;
}
}
</pre>
</syntaxhighlight>
 


==MatlabTutorial==
==MatlabTutorial==
Line 303: Line 312:
Note that BCI2000RemoteLib's file name has a "64" appended when it was built in 64 bit mode, and a "32" if built iin 32 bit mode.
Note that BCI2000RemoteLib's file name has a "64" appended when it was built in 64 bit mode, and a "32" if built iin 32 bit mode.
In this tutorial, we will be using the 64 bit version.
In this tutorial, we will be using the 64 bit version.
<pre>
<syntaxhighlight lang="matlab">
%% c library load, initial part
%% c library load, initial part
BCI2000root = 'C:\bci2000.x64';
BCI2000root = 'C:\bci2000.x64';
Line 311: Line 320:
end  
end  
libfunctions('bci')
libfunctions('bci')
</pre>
</syntaxhighlight>
</li>
</li>
<li> Locate Operator.exe in the prog folder. Recover the memory, change the directory, and make the window visible in BCI2000. Again, modify the file path if it differs.  
<li> Locate Operator.exe in the prog folder. Recover the memory, change the directory, and make the window visible in BCI2000. Again, modify the file path if it differs.
<pre>%need to call BCI2000Remote_Delete to recover the memory
 
<syntaxhighlight lang="matlab">
%need to call BCI2000Remote_Delete to recover the memory
bciHandle = calllib('bci', 'BCI2000Remote_New');
bciHandle = calllib('bci', 'BCI2000Remote_New');
calllib('bci', 'BCI2000Remote_SetOperatorPath', bciHandle, fullfile(BCI2000root,'prog','Operator'));
calllib('bci', 'BCI2000Remote_SetOperatorPath', bciHandle, fullfile(BCI2000root,'prog','Operator'));
Line 329: Line 340:
calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Show window; Set title ${Extract file base $0}', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Show window; Set title ${Extract file base $0}', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Reset system', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Reset system', 0);
</pre>
</syntaxhighlight>
</li>
</li>
<li> Add new states, events, or parameters before starting up the system. Note that it is greatly preferred to use events instead of states because of timing precision.
<li> Add new states, events, or parameters before starting up the system. Note that it is greatly preferred to use events instead of states because of timing precision.
<pre>
<syntaxhighlight lang="matlab">
% Create new parameter (must be done before startup)
% Create new parameter (must be done before startup)
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Add Parameter Application:TestParameterField string TestParameter= FirstNewParameter % % %', 0);  
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Add Parameter Application:TestParameterField string TestParameter= FirstNewParameter % % %', 0);  


% Define events
% Define events
% Define new event with 2 bytes of information (2 colors)
% Define new event with 1 bit of information (2 colors)
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'add event Square 1 0', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'add event Square 1 0', 0);
</pre>
</syntaxhighlight>
</li>
</li>
<li>Add in the proper modules (Signal Generator, Signal Processor, and Application). Refer to the documentation [[Technical_Reference:BCI2000Remote_Library]] for more information on BCI2000 remote functions. Also refer to the example Matlab code under [[Programming_Reference:BCI2000Remote_Class#Matlab_Example]].</li>
<li>Add in the proper modules (Signal Generator, Signal Processor, and Application). Refer to the documentation [[Technical_Reference:BCI2000Remote_Library]] for more information on BCI2000 remote functions. Also refer to the example Matlab code under [[Programming_Reference:BCI2000Remote_Class#Matlab_Example]].</li>
<pre>
<syntaxhighlight lang="matlab">
% Startup system localhost
% Startup system localhost
calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Startup system localhost', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Startup system localhost', 0);
Line 353: Line 364:
% Wait for connected before loading parameters!
% Wait for connected before loading parameters!
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Wait for Connected', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Wait for Connected', 0);
</pre>
</syntaxhighlight>
<li> Load parameter files, modify parameters directly, and add watches after BCI2000 is connected. It can also be helpful to wait for bci2000 to start running (collecting data) before proceeding.
<li> Load parameter files, modify parameters directly, and add watches after BCI2000 is connected. It can also be helpful to wait for bci2000 to start running (collecting data) before proceeding.
<pre>
<syntaxhighlight lang="matlab">
% Load parameter files
% Load parameter files
calllib('bci', 'BCI2000Remote_LoadParametersRemote', bciHandle, fullfile(BCI2000root,'parms','fragments','amplifiers','SignalGenerator.prm'));
calllib('bci', 'BCI2000Remote_LoadParametersRemote', bciHandle, fullfile(BCI2000root,'parms','fragments','amplifiers','SignalGenerator.prm'));
Line 365: Line 376:
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'visualize watch Square', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'visualize watch Square', 0);


% Wait for BCI2000 to start running before starting application
% Wait for the user to click SetConfig and Start
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Wait for Running', 0);
calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Wait for Running', 0);
</pre>
</syntaxhighlight>
</li>
</li>
<li> While BCI2000 is running you can also get and set event and state values, and also get parameter values. Note that you cannot modify parameter values while BCI2000 is running.  
<li> While BCI2000 is running you can also get and set event and state values, and also get parameter values. Note that you cannot modify parameter values while BCI2000 is running.  
<pre>
<syntaxhighlight lang="matlab">
% Get parameter value
% Get parameter value
SamplingRate = calllib('bci', 'BCI2000Remote_GetParameter', bciHandle, 'SamplingRate');
SamplingRate = calllib('bci', 'BCI2000Remote_GetParameter', bciHandle, 'SamplingRate');
Line 391: Line 402:
% Stop running BCI2000
% Stop running BCI2000
calllib('bci', 'BCI2000Remote_SetStateVariable', bciHandle, 'Running', 0);
calllib('bci', 'BCI2000Remote_SetStateVariable', bciHandle, 'Running', 0);
</pre>
</syntaxhighlight>
</li>
</li>
</ol>
</ol>

Latest revision as of 23:13, 14 May 2025

Description

BCI2000Remote is a proxy interface class to the BCI2000 Operator module, and allows to start up, configure, and control BCI2000 from other applications. Internally, it maintains a telnet connection to the Operator module, and sends Operator Scripting commands to control it. However, no knowledge of these scripting commands is required in order to use the BCI2000Remote class from your own application.

BCI2000Remote is most useful when writing applications in C++, or in another language for which bindings to the BCI2000RemoteLib library exist, such as Python, or MATLAB.

Note

BCI2000Remote is a means of interfacing with the BCI2000 Operator module meaning that there are potentially hundreds of ways we leverage this tool to have a meaningful interface with BCI2000. Because of this we will illustrate a few different integrations using different languages. This "How-to" will be separated into three separate sections: Python, C++, and Matlab.

Python Tutorial

  1. Find your Python folder. If you have an existing Python environment with your code find it using the Sys Library like this:
    import sys
    
    locate_python = sys.exec_prefix
    print(locate_python)
    
  2. Locate your BCI2000Remote.py file which should have compiled into your prog folder. Find where in your Python code you wish to integrate BCI2000. In this example I will show the minimum requirements for integration with BCI2000:
    # Set BCI2000 path
    import sys, time
    sys.path.append('C:\\BCI2000.x64\\prog')
    
    # BCI2000 setup
    import BCI2000Remote
    bci = BCI2000Remote.BCI2000Remote()
    bci.WindowVisible = True
    bci.WindowTitle   = 'BCI2000 Remote Python'
    bci.Connect()
    bci.Execute('cd ${BCI2000LAUNCHDIR}')
    bci.Execute('ADD EVENT Square 2 0')
    bci.StartupModules(('SignalGenerator', 'DummySignalprocessing', 'DummyApplication'))
    
    bci.Execute('Wait for Connected')
    bci.LoadParametersRemote('..\\parms\\fragments\\amplifiers\\SignalGenerator.prm')
    bci.Execute('Wait for Running')
    bci.Execute('Set event Square 1')
    

    Here is how you import BCI2000Remote:


    Here is how you instantiate the operator object:


    Here is how to customize the operator and connect to it:


    Here is how you add your states:


    How to specify your signal source, signal processing, and application modules:


    How to load a parameter file(you can learn more about parameters here):


    How to connect and issue commands to BCI2000:

  3. And finally, how to tell BCI2000 to set states to a value during runtime:


    Now that you've added those components to your code all you have to do is run your code. You should see the BCI2000 operator along with the system log, source watcher, and the timing window.


C++ Tutorial

  1. Open the C++ file or solution you would like to integrate with BCI2000 in Visual Studio, and find where it is located on your computer.
  2. Navigate to the program's properties, and make the following changes:
    • Under Configuration Properties -> C++ -> General, add the following folders from BCI2000 (64-bit)'s src folder: \core\Operator\BCI2000Remote, \shared\utils\Lib, \shared\config.
    • Navigate to Configuration Properties -> Linker -> Input, and add ws2_32.lib to Additional Dependencies.
    • Under Configuration Properties -> C++ -> Advanced, add 4996 to the Disable Specific Warnings section.
  3. Add your Operator executable and the BCI2000RemoteLib dynamic library to the same directory as the program you intend to integrate. This can be found in the prog folder.
  4. Also, add the following files to the directory with your program and Operator.exe:
    • BCI2000Connection.cpp
    • BCI2000Connection.h
    • BCI2000Remote.cpp
    • BCI2000Remote.h
    • BCI2000RemoteLib.cpp
    • BCI2000RemoteLib.h
    • SelfPipe.cpp
    • SelfPipe.h
    • sockstream.cpp
    • sockstream.h

  5. Make sure that you include all of your dependencies including BCI2000Remote.h
    #include "BCI2000Remote.h"
    #include <string>
    #include <vector>
    #include <iostream>
    
  6. Next, instantiate the BCI2000Remote object
    int main( int argc, char* argv[] )
    {
      // Instantiate a BCI2000Remote object
      BCI2000Remote bci;
      // Assume that Operator executable resides in the same directory as this program.
      std::string path = ( argc > 0 ) ? argv[0] : "";
      size_t pos = path.find_last_of( "\\/" );
      path = ( pos != std::string::npos ) ? path.substr( 0, pos + 1 ) : "";
      // Start the Operator module, and connect
      bci.OperatorPath( path + "Operator" );
      if( !bci.Connect() )
      {
        std::cerr << bci.Result();
        return -1;
      }
    
  7. Specify your startup modules and any flags you wish to start them with
      // Startup modules
      std::vector<std::string> modules{ "SignalGenerator --LogMouse=1", "ARSignalProcessing", "CursorTask" };
      if( !bci.StartupModules( modules ) )
      {
        std::cerr << bci.Result();
        return -1;
      }
    
  8. Load any parameter files and set subject information
    bci.LoadParametersRemote( "../parms/examples/CursorTask_SignalGenerator.prm" );
      bci.SubjectID( "SUB" );
      // Start a run
      if( !bci.Start() )
      {
        std::cerr << bci.Result();
        return -1;
      }
    
  9. And here we just have BCI2000 send us back a feedback signal:
      std::string state;
      while( bci.GetSystemState( state ) && state == "Running" )
      {
        double value = 0;
        bci.GetControlSignal( 1, 1, value );
        std::cout << "Control signal: " << value << ", press Enter to proceed" << std::flush;
        std::string line;
        std::getline( std::cin, line );
      }
      return 0;
    }
    
  10. Now that you've added those components to your code all you have to do is compile and run it. You should see the BCI2000 operator along with the system log, source watcher, and the timing window. Note: Be sure to compile this in your prog folder. This can be done by navigating again to Configuration Properties -> General, and changing the Output Directory to the path of the BCI2000 prog folder.
#include "BCI2000Remote.h"
#include <string>
#include <vector>
#include <iostream>

int main( int argc, char* argv[] )
{
  // Instantiate a BCI2000Remote object
  BCI2000Remote bci;
  // Assume that Operator executable resides in the same directory as this program.
  std::string path = ( argc > 0 ) ? argv[0] : "";
  size_t pos = path.find_last_of( "\\/" );
  path = ( pos != std::string::npos ) ? path.substr( 0, pos + 1 ) : "";
  // Start the Operator module, and connect
  bci.OperatorPath( path + "Operator" );
  if( !bci.Connect() )
  {
    std::cerr << bci.Result();
    return -1;
  }
  // Startup modules
  std::vector<std::string> modules{ "SignalGenerator --LogMouse=1", "ARSignalProcessing", "CursorTask" };
  if( !bci.StartupModules( modules ) )
  {
    std::cerr << bci.Result();
    return -1;
  }
  // Load a parameter file, and set subject information
  bci.LoadParametersRemote( "../parms/examples/CursorTask_SignalGenerator.prm" );
  bci.SubjectID( "SUB" );
  // Start a run
  if( !bci.Start() )
  {
    std::cerr << bci.Result();
    return -1;
  }
  // Print feedback signal
  std::string state;
  while( bci.GetSystemState( state ) && state == "Running" )
  {
    double value = 0;
    bci.GetControlSignal( 1, 1, value );
    std::cout << "Control signal: " << value << ", press Enter to proceed" << std::flush;
    std::string line;
    std::getline( std::cin, line );
  }
  return 0;
}

MatlabTutorial

  1. Open the Matlab file you would like to integrate with BCI2000.
  2. Locate the BCI2000RemoteLib file in the BCI2000 prog folder, and BCI2000RemoteLib.h in src\core\Operator\BCI2000Remote, and load these into the Matlab file. Modify the file paths in loadlibrary(...) as needed. Note that BCI2000RemoteLib's file name has a "64" appended when it was built in 64 bit mode, and a "32" if built iin 32 bit mode. In this tutorial, we will be using the 64 bit version.
    %% c library load, initial part
    BCI2000root = 'C:\bci2000.x64';
    if not(libisloaded('bci'))
        loadlibrary(fullfile(BCI2000root,'prog','BCI2000RemoteLib64'),...
            fullfile(BCI2000root,'src','core','Operator','BCI2000Remote','BCI2000RemoteLib.h'), 'alias', 'bci')
    end 
    libfunctions('bci')
    
  3. Locate Operator.exe in the prog folder. Recover the memory, change the directory, and make the window visible in BCI2000. Again, modify the file path if it differs.
    %need to call BCI2000Remote_Delete to recover the memory
    bciHandle = calllib('bci', 'BCI2000Remote_New');
    calllib('bci', 'BCI2000Remote_SetOperatorPath', bciHandle, fullfile(BCI2000root,'prog','Operator'));
    
    % if we fail cto establish a connection to BCI2000Remote
    if calllib('bci', 'BCI2000Remote_Connect', bciHandle) ~= 1
        fprintf('bci connect fail!')
        calllib('bci', 'BCI2000Remote_Delete', bciHandle); % call BCI2000Remote_Delete to recovery the memory
        return
    end
    
    % Startup BCI2000
    calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Change directory $BCI2000LAUNCHDIR', 0);
    calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Show window; Set title ${Extract file base $0}', 0);
    calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Reset system', 0);
    
  4. Add new states, events, or parameters before starting up the system. Note that it is greatly preferred to use events instead of states because of timing precision.
    % Create new parameter (must be done before startup)
    calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Add Parameter Application:TestParameterField string TestParameter= FirstNewParameter % % %', 0); 
    
    % Define events
    % Define new event with 1 bit of information (2 colors)
    calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'add event Square 1 0', 0);
    
  5. Add in the proper modules (Signal Generator, Signal Processor, and Application). Refer to the documentation Technical_Reference:BCI2000Remote_Library for more information on BCI2000 remote functions. Also refer to the example Matlab code under Programming_Reference:BCI2000Remote_Class#Matlab_Example.
  6. % Startup system localhost
    calllib('bci', 'BCI2000Remote_Execute', bciHandle,'Startup system localhost', 0);
    
    % Establish connection to three modules
    SourceModule = 'SignalGenerator';
    modules      = libpointer('stringPtrPtr', {[SourceModule ' --local --LogKeyboard=1'], 'DummySignalProcessing', 'DummyApplication'});
    calllib('bci', 'BCI2000Remote_StartupModules2', bciHandle, modules, 3);
    
    % Wait for connected before loading parameters!
    calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Wait for Connected', 0);
    
  7. Load parameter files, modify parameters directly, and add watches after BCI2000 is connected. It can also be helpful to wait for bci2000 to start running (collecting data) before proceeding.
    % Load parameter files
    calllib('bci', 'BCI2000Remote_LoadParametersRemote', bciHandle, fullfile(BCI2000root,'parms','fragments','amplifiers','SignalGenerator.prm'));
    
    % Set parameter values
    calllib('bci', 'BCI2000Remote_SetDataDirectory', bciHandle, fullfile(BCI2000root,'data','BJH'));
    
    %Set watches to appear automatically
    calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'visualize watch Square', 0);
    
    % Wait for the user to click SetConfig and Start
    calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Wait for Running', 0);
    
  8. While BCI2000 is running you can also get and set event and state values, and also get parameter values. Note that you cannot modify parameter values while BCI2000 is running.
    % Get parameter value
    SamplingRate = calllib('bci', 'BCI2000Remote_GetParameter', bciHandle, 'SamplingRate');
    fprintf(['\nSamplingRate: ' num2str(SamplingRate) 'Hz\n'])
    
    % Get event value
    [~,~,~,Square]=calllib('bci', 'BCI2000Remote_GetEventVariable', bciHandle, 'Square', 0.0);
    
    % BCI2000 set white rectangle to 1 (true)
    calllib('bci', 'BCI2000Remote_Execute', bciHandle, 'Set event Square 1', 0);
    
    % Get state value
    % Immediately after data block has been acquired from hardware, the 
    % DataIOFilter writes a 16-bit millisecond-resolution time stamp into the 
    % SourceTime state. Block duration is measured as the difference between
    % two consecutive time stamps.
    [~,~,~,SourceTime]=calllib('bci', 'BCI2000Remote_GetStateVariable', bciHandle, 'SourceTime', 0.0);
    fprintf(['\nSourceTime: ', num2str(SourceTime), '\n'])
    
    % Stop running BCI2000
    calllib('bci', 'BCI2000Remote_SetStateVariable', bciHandle, 'Running', 0);
    

Video

Also see the PsychoPy page for more details on the installation process, APIs, and hooks.

See also