StateServer 1.6.9
Compiled `c` application to handle task state logging and timing.
Loading...
Searching...
No Matches
State Server

Compiled c application to handle task state logging and timing.

(Return)


Contents

State Machine

The wrist center-out task state machine for the NHP task runs as shown by the following image generated using graphviz:
.
To modify this image, you need to update the corresponding lines in state_transition_flowchart.dot (which is located in the project root of this repository). After modifying state_transition_flowchart.dot, you must regenerate the static image file that is used in the documentation. To do so, first make sure that graphviz is installed on your device and that the associated binaries folder (e.g. C:/Program Files/graphviz/bin) is in your environment PATH variable. With graphviz installed and on the PATH, issue the following command from a Windows Terminal:

dot -Tpng state_transition_flowchart.dot -o "%NML_DOXY_DOCS_DIRECTORY%/StateServer/html/state_transition_flowchart.png"

Compiling

Main Applications

NHP Wrist State Server

This application launches the State Server on a Windows host. It should be run on some other machine than the Plexon rig computer, but preferably still a good computer. Important: config.yaml must be present in whichever folder contains the NHP_Wrist_State_Server.exe when it is run. Therefore, if you copy the executable out of that folder make sure you copy config.yaml along with it. You must properly set up config.yaml according to the current configuration of devices in your task network, or this executable will not work!

To re-compile the executable bin/NHP_Wrist_State_Server.exe use the following command:

cd %NML_NHP_C_PROJECTS%/StateServer && gcc src/state_server.c -o bin/NHP_Wrist_State_Server.exe -Iinclude -Llib -lNetwork -lws2_32 -lLogUtilities -lTaskParameters -lDataStructures -lTiming -lMathUtilities -lCalibrationUtilities && doxyincrement.bat && doxygen > %NML_NHP_C_PROJECTS%/doxygen_output.log

Note 1: it is critically important to link ws2_32 only after Network; also, since the other libraries include <Windows.h>, -lws2_32 must precede any of the other libraries.
Note 2: during the compilation and linking of the static lib/Network.lib (in NetworkUtilities), please make sure to not link -lws2_32 in the gcc static object file generation step. The static library does not require external libraries; the external libraries should only be linked in the final compilation step (i.e. when producing a .dll dynamic link library or when producing a .exe executable to run the application).

More Details on State Server
NHP_Wrist_State_Server.exe has 5 main threads: a "Clock" thread, a "Controller" thread, an "Input" thread, a "State" thread, and an "Output" thread. The threads are managed using pthread_mutex_t and pthread_cond_t to ensure proper synchronization, cycling in the sequence Clock > Controller > Input > State > Output > Clock > ... in a manner that is guaranteed to complete one full cycle before any other thread completes another round of handling its duties.

  • The timestamp of each update cycle is generated at the beginning of every round in the handler thread rotation, from the Clock thread. Essentially the only job of this thread is to wait for the specified amount of time (currently set to 0.001s) upon waking with control of the mutex (which is when it starts the desired timer). On a Windows 64-bit machine, the timer resolution for this wait cycle should typically be dictated by a clock with 100MHz precision (i.e. it can be as fast to update as 10-us although that is really not recommended).
  • The Controller handler thread receives inputs from a "Controller" network device, which could be the same as the device running this state machine but might have to be a separate computer. The "Controller" computer can likely be a "light-weight" machine as it really just serves as a user interface/front-end. The Control commands do things like put the task into an Idle state, Enable/Disable Logging, or Shutdown the entire interface. This is also the phase where parameter updates are taken (again from the "Controller" computer). Any parameter updates that need to be relayed to the "Renderer" device are also forwarded at this stage. Finally, any experimentally-relevant metadata that breaks up files, like changing Subject or starting a new "Set" (i.e. swapping Orientation or other behavioral variable) is handled in this stage and sets flags in the event that logging is enabled.
  • The Input handler thread receives new cursor positions (e.g. from PotentiometerClient.exe running on the Plexon rig or other networked machine connected to the Omniplex network streams). This allows flexibility in the way the inputs are treated. No transformation on the Input position happens; it is purely a relay to the TaskRender machine that ensures concurrency for logging the state of the task, including the cursor.
  • The State handler thread is where state checks occur. These checks include calculations like determining if the cursor is within a specific target, or if sufficient time has proceeded to allow a hold state to advance to the next task state.
  • The Output handler thread mediates sending the cursor position to the "Renderer" device. It also sends the target locations to the "Renderer" device. Target positions are updated during the ADVANCE transition into T1_MOVE; additional target messages are generated during T2_SHOW and T1_GO states to show T2 and hide T1, respectively.
    • At the end of the Output handling, the current state is logged along with its timestamp. This includes the cursor position, task state, transition state, and some other details.

Test Applications

To re-compile all test executables, use the following bash command:

cd %NML_NHP_C_PROJECTS%/StateServer && gcc tests/test_controller.c -o bin/tests/NHP_Wrist_Controller_Test.exe -Iinclude -Isrc -Llib -lNetwork -lws2_32 -lLogUtilities -lDataStructures && gcc tests/test_parameters.c -o bin/tests/NHP_Wrist_Parameters_Test.exe -Iinclude -Isrc -Llib -lNetwork -lws2_32 -lTaskParameters -lLogUtilities -lDataStructures && gcc tests/test_log_reader.c -o bin/tests/NHP_Wrist_Log_Reader_Test.exe -Iinclude -Isrc -Llib -lNetwork -lws2_32 -lLogUtilities -lTaskParameters -lDataStructures

NHP Wrist Controller Test

This should be run after starting NHP_Wrist_State_Server.exe. It sends a few test commands to the server, checking that the controllerHandlerThread correctly receives the control commands to enter the idle state, exit the idle state, and shut down.

To re-compile the executable bin/tests/NHP_Wrist_Controller_Test.exe use the following command:

gcc tests/test_controller.c -o bin/tests/NHP_Wrist_Controller_Test.exe -Iinclude -Isrc -Llib -lNetwork -lws2_32 -lLogUtilities -lDataStructures

NHP Wrist Parameters Test

This should be run after starting NHP_Wrist_State_Server.exe. It sends an example parameter message to the server, checking that the controllerHandlerThread correctly updates the received parameters message.

To re-compile the executable bin/tests/NHP_Wrist_Parameters_Test.exe use the following command:

gcc tests/test_parameters.c -o bin/tests/NHP_Wrist_Parameters_Test.exe -Iinclude -Isrc -Llib -lNetwork -lws2_32 -lTaskParameters -lLogUtilities -lDataStructures

NHP Wrist Log Reader Test

This should be run after starting NHP_Wrist_State_Server.exe. It sends an example parameter message to the server, checking that the outputHandlerThread correctly issues a sound request message (i.e. as would occur on different task cues in the corresponding state) and finally that it correctly issues a reward request message (which prompts sending back a message with updated target locations).

To re-compile the executable bin/tests/NHP_Wrist_Log_Reader_Test.exe use the following command:

gcc tests/test_log_reader.c -o bin/tests/NHP_Wrist_Log_Reader_Test.exe -Iinclude -Isrc -Llib -lNetwork -lws2_32 -lLogUtilities -lTaskParameters -lDataStructures

Note about gcc

Note that to use gcc on a Windows 64-bit architecture, the simplest way is to download msys2, which will allow you to use pacman from an msys2 terminal. You can first check to see if you already have gcc installed:

pacman -Q | grep mingw-w64-x86_64-gcc

If you see anything in the terminal following this command, it means you already have gcc. Otherwise, you need to install it (and probably the rest of the toolchain, such as a linker etc.):

pacman -S mingw-w64-x86_64-toolchain

This will give several options for what you can install. If you are unsure what to do, just install all of them.
Finally, you may also want a toolchain for compiling 32-bit applications from your 64-bit Windows operating system. In that case, you can try:

(bash)
pacman -S mingw-w64-i686-toolchain

The last step is to make sure the folder with the correct binaries are on your PATH environment variable. Probably the best strategy here, on a Windows device, is as follows:

  1. Open the Start menu and type Environment, this should bring up a Control Panel shortcut to "Edit the System Environment Variables." Click that.
  2. Click "Environment Variables..." at the bottom right.
  3. Under System Variables, click "New..." and define a new environment variable: MINGW_PATH. If you installed msys2 in the default location, then go to C:/mingw64. You will be looking for the sub-folder containing binaries. In my install, that is located at C:\msys64\mingw64\bin – so that is my MINGW_PATH environment variable.
  4. Under User Variables, find Path. Click Edit... with Path selected.
  5. In the new popup, click New to add a new Path value. Enter MINGW_PATH%. Now, you can add or remove MINGW_PATH% from the user Path variable depending on what compiler needs you have. Click on the newly added value, and click Move Up until it is at the top of the list. This ensures we don't accidentally find gcc somewhere else and use a different unintended version. Note that if you want to switch between i.e. C:\msys64\mingw32\bin and C:\msys64\mingw64\bin it might just be easiest to change the value of MINGW_PATH environment variable.