CGX Wireless StimTrigger and Neurobs Presentation

Hello,
I am struggling with setting up a Cedrus Wireless StimTrigger with Presentation. The StimTrigger is connected to the stim computer through USB, but emulates a serial port via FTDI drivers. The StimTrigger is recognized as a USB Serial Port (COM5) in the Device Manager. I have set up the port in the Presentation Settings as indicated in the Presentation demo:

Rate:115200
Parity: None
Data bits: 8
Stop bits: 1
(all other options are set either to “disable” or “off”. The FIFO interrupt option is not selected.)

A couple of problems here.

  1. When I click the “Test” button, nothing happens.
  2. When I run the Presentation demo, it does work and sends the codes. However, the code provided by Presentation is somehow obscure to me:
begin;
begin_pcl;
output_port soport = output_port_manager.get_port( 1 );

# set pulse width
soport.send_code(109); #m
soport.send_code(112); #p
soport.send_code(144);
soport.send_code(1);
soport.send_code(0);
soport.send_code(0); #400, little endian

soport.send_code(109); #m
soport.send_code(104); #h
soport.send_code(0); #all lines low
soport.send_code(0); #extra byte
wait_interval(600);

soport.send_code(109); #m
soport.send_code(104); #h
soport.send_code(1); #line 1 high, others low
soport.send_code(0); #extra byte  
wait_interval(600);

soport.send_code(109); #m
soport.send_code(104); #h
soport.send_code(2); #line 2 high, others low
soport.send_code(0); #extra byte  
wait_interval(600);

soport.send_code(109); #m
soport.send_code(104); #h
soport.send_code(3); #line 1 and 2 high, others low 
soport.send_code(0); #extra byte  
wait_interval(600);

The codes sent are just 1, 2, and 3. I guess the remaining send_code lines (i.e., the “m”, “h”, “p”, and “extra byte” lines) are just the way the stim trackers sends the markers. Can anyone explain to me what they are and why it is like that? It sounds like I will need to change the whole code…

I have also found out that the Lab Streaming Layer might be an easier way out of this. Both Presentation, and the CGX wireless stim tracker and headset are fully supported by LSL. So I was wondering if you have any insight about that.

Thank you in advance!

The Presentation code looks correct. When you run it, do either of the “Code” LEDs on StimTrigger’s front panel light up? One of them should.

I don’t know what the “Test” button does in Presentation. It might simply be opening the serial port and closing it to verify that it can establish a connection.

Regarding LSL, we are considering a version of StimTracker that includes built-in LSL support, but it doubt that it will work simultaneously with CGX.

Thanks, I will check on Monday when I get back to the lab.

Can you also expand on the reason and the meaning behind such a (allow me to say) odd structure to send triggers? It does not look like very much user friendly, to be honest…

I have spent some time trying to figure out what the numbers in the parentheses actually mean, but honestly I can’t quite understand it.

# set pulse width
soport.send_code(109); #m
soport.send_code(112); #p

what does these two line do exactly? and why the second line sends 104 (instead of 112) when sending the actual port code?

soport.send_code(144);
soport.send_code(1);
soport.send_code(0); #400, little endian
soport.send_code(0); #extra-byte

As far as I could understand, this sends the actual pulse width (144 1 0 = 90 1 0 in little-endian hex), which is equals to 400 in decimal numbers. But why 400?

Sorry for the many questions, I am just trying to understand the code so I can adjust it to my own needs. I guess a related question I have is how to communicate with the device through the XID commands (especially the input commands, which I figured it would also help interpreting the numbers above). I have searched on the website but I can’t seem to understand where to type in the commands. Can anyone help?

Thank you in advance!

The words “user friendly” and “programming” are not usually used in the same sentence! :smiley:

The “mh” and “mp” commands were an improvement over earlier commands (that are now gone from the firmware). We have since introduced the “mx” command as well; see XID Commands.

If you want even more powerful features, you can have StimTrigger send a sequence of pulses.

These commands are not designed to be user friendly – I don’t see how they can be. They are typically implemented to fulfill a specific need. For example:

  • The “mx” command is what SuperLab version 6.3 and later use. It helped us implement features that were not possible before; see this blog post.

  • The sequence of pulses commands are needed by researchers presenting media (audio, but mostly movies) and want to send event markers at specific moments while the media is playing.

If you want user friendliness, SuperLab is a better bet.

Communicating with the firmware directly is a task reserved for programmers, or researchers with some programming experience.

For example:

# set pulse width
soport.send_code(109); #m
soport.send_code(112); #p

what does these two line do exactly?

109 is the ASCII code for the letter ‘m’ and 112 is the ASCII code for the letter ‘p’. See ASCII Table.

The best we can do in this regard is to document the firmware and to provide support code, e.g. our C++ and Python libraries or Matlab sample code. Unfortunately, we cannot assist with each individual user’s code.

1 Like

Hi Hisham, thank you for your message.

I apologize for the misunderstanding – I do not seek assistance with my code. I am just finding hard to understand how to even use the python library for communicating with the firmware. I have cloned the git folder from git and updated the submodules. However, when I try to run the very first line from the python sample code in the folder:

import pyxid2
import time

scanner = pyxid2.XIDDeviceScanner.GetDeviceScanner()

It gives the following error:

AttributeError: module 'pyxid2' has no attribute 'XIDDeviceScanner'

When trying to list all the methods in the module ‘pyxid2’, I only get what looks like a list of constructors:

>>> import pyxid2
>>> dir(pyxid2)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

What am I missing something?

I am adding here two more questions, I would be grateful if you could answer them!

  1. Looking again at the code I posted above:

In the description of the set pulse width command, it says:

The parameter is a four byte binary value that forms a little-endian, 32-bit unsigned integer.

However, I am a little lost on how to interpret this. The little-endian hex conversion of 400 is actually 90 01. Why is it 144 1 0 0? I feel like there is an important bit of information I am missing here (which I think would be helpful for future users too).

  1. I think I do have a general understanding of what the stim trigger does. My question now is the following: given that there are specific ASCII values that are used for sending specific commands (e.g., mh, mp, mx, …), are those not allowed to be used as port codes? It would be something useful to know before collecting data so to avoid conflicts in the trigger flow.

Thank you in advance for your help!

I ran the GitHub repo question by a colleague and he didn’t know what the issue is either. However, he did recommend that you get the pyxid2 library from PyPi instead:

Regarding the Presentation code, we don’t have any experience with it in-house. We use C++ internally. It would be better to ask the good folks at NBS.

Thank you, Hisham for your message. I will try to use the PyPi version of the library.

Does your reply re: Presentation also apply to the following question?

Apologies for reiterating this, but to me it seems like a more general question about the functioning of the XID commands and the usage of potentially unusable digits, rather than a software-specific one – at least that was my original intent.