Register writes and updates
System A (your computer) and Hardware B (the data acquisition hub) are operating in parallel. How do they communicate complex information effectively, without interfering with each others' processes?
This problem presents an engineering challenge our team has solved through the use of Register Writes and Register Updates.
Register Writes
Our hardware has onboard system settings and a current configuration saved in what we call the device register. A copy of this data is saved on your experiment computer as well. We call this copy the local register.
When we write a line of MATLAB or Python code that tells our VPixx device to do something, we are changing the contents of the local register on your PC; this has no impact on our device register. In order to update our device register with the changes we have made to the local register, we need to perform a register write.
A major advantage to register writing is that it allows several tasks to be executed simultaneously. Simply write multiple commands to the local register, and execute a single register write to enable all changes on the device register at the same time.
Another advantage to using registers is that you can wait for a specific video event to perform the write. This allows us to synchronize our experiment I/O with properties of the video signal with zero delay. Below is a list of currently supported register write commands:
Perform a register write immediately | |
---|---|
MATLAB/Psychtoolbox | Datapixx(‘RegWr’) |
Python (libdpx wrapper) | DPxWriteRegCache() |
Python (object-oriented) | device.writeRegisterCache() |
Perform a register write on next vertical sync pulse/start of the next video frame | |
MATLAB/Psychtoolbox | Datapixx(‘RegWrVideoSync’) |
Python (libdpx wrapper) | DPxWriteRegCacheAfterVideoSync() |
Python (object-oriented) | device.writeRegCacheAfterVideoSync() |
Perform a register write on next instance of a user-defined sequence of pixels (learn more) | |
MATLAB/Psychtoolbox | Datapixx(‘RegWrPixelSync’) |
Python (libdpx wrapper) | DPxWriteRegCacheAfterPixelSync() |
Python (object-oriented) | device.writeRegCacheAfterPixelSync() |
Our Python tools come in two flavours, which reflect two distinct programming styles. For more details, see The two flavours of pypixxlib
There are a handful of special functions (like ‘Open’ and ‘Close’) which are automatically passed to the device register. These functions don’t need to be followed by a register write.
Register Updates
Now we know how to send one-way commands to our hardware. To update the information in the local register, such that it reflects the current state of the device register, we must perform a two-way exchange: write to the device register, then retrieve data from the device.
This is done via register update, also known as a register write-read.
There are two commands inherent in an update, reflecting each step of the two way communication: the initial register write with the data request, and the data transfer back to the PC. We have a series of commands which execute these steps in a single line of code. Remember that every update performs a write as its first step, so any other commands waiting in the local register will also be executed.
Perform a register update immediately | |
---|---|
MATLAB/Psychtoolbox | Datapixx(‘RegWrRd’) |
Python (libdpx wrapper) | DPxUpdateRegCache() |
Python (object-oriented) | device.updateRegisterCache() |
Perform a register update on next vertical sync pulse/start of the next frame | |
MATLAB/Psychtoolbox | Datapixx(‘RegWrRdVideoSync’) |
Python (libdpx wrapper) | DPxUpdateRegCacheAfterVideoSync() |
Python (object-oriented) | device.updateRegCacheAfterVideoSync() |
It’s important to keep in mind that register updates are blocking functions. That is, everything else in your script is put on hold until the data transfer is finished. This is something to be aware of when deciding between a register write, versus a register update.
When to use a register write vs. update
Register writes are used whenever status changes need to be made quickly, without blocking subsequent commands. No data is returned to the local register.
Register updates are used in situations where data must be collected from the device register (e.g., recorded data, status updates, current states of the various I/O subsystems). The local register is updated to reflect the current state of the device register.