Issue reading parallel port pin for button box

I fixed it! In case anyone else runs into this issue, here’s what happened. Edit3: I’m adding some more info that I’ve put elsewhere in this forum on parallel ports, so that this post can act as a troubleshooting start point for anyone who finds it.

The control register
In a parallel port, bit 5 of the control register (located at the parallel port’s base address + 2) will control the directional flow of the data. If this bit is flipped, then you may be unable to read any changes. Setting this bit does seem to be included in the PsychoPy parallel class port instantiation, but I think it’s set to 0 whereas we needed it set to 1.

image

Pin 7 on the control register would correspond to bit 5, which is the PS/2 data direction control. (Recall that pins 2-9 map onto data bits 0-7.) Some supplemental reading:

  • Page 4 of this PDF about the Control Register bit 5 (PS/2 Data direction)
  • Lines 52-57 of the PParallelInpOut class source code, where this bit is flipped when instantiating a parallel port
  • This website’s thorough write-up on parallel ports. Look for discussion on “control bit 5”.

Flow bit fixes

Original solution: I used the ctypes/windll function library that underlies parallel port reading with the InpOut32.dll driver in PsychoPy to read and flip this bit accordingly. Now that I think about it, the PsychoPy parallel class should be able to read this bit if we use it to read the control register address… Will report back on that.

Edit1 | Second realization: Also, there was a similar issue reported here where the fix came from using the pyparallel class instead. Their fix and our fix are fundamentally the same: pyparallel has a function that allows you to set the data direction, which is flipping bit 5 of the control register.

Edit2 | Third realization, 2 years later: I’ll note that the parallel class in PsychoPy also specifically flips data flow bits upon port instantiation, see snippet here. I modified the PsychoPy code in our version to prevent this from happening… Maybe I should make a pull request to make the change if I get un-lazy. :slight_smile:

Test code

For checking then flipping:

port_address = 0x3048 # hex address of parallel port
ctrl_port = parallel.ParallelPort(port_address+2) # ctrl port found at +2
if ctrl_port.readPin(7) is 0:
        ctrl_port.setPin(7,1)

For checking, flipping, then seeing if button responses are registered assuming that the button response is mapped to pin 10:

from psychopy import parallel

# instantiate ports
port = parallel.ParallelPort(0x4FF8)
ctrl_port = parallel.ParallelPort(0x4FF8+2)

# check if direction bit is set to 0 in the control register, if so flip it
if ctrl_port.readPin(7) == 0: 
   ctrl_port.setPin(7, 1)

# check whether a button has been pressed
pressed = False
while not pressed:
   response = port.readPin(10) # returns 1 if pressed, 0 if not
   if response:
      print("Hooray! Button response registered.")
      pressed = True

Read the button box documentation
We were using a RESPONSEPixx/MRI button box (4-button handheld). No one documented how the system was installed, and it turned out that a parallel port adapter provided by the company was not used, thus mapping the button responses onto unexpected pins. For us, the red button was being mapped onto pin 1 (i.e., strobe of the control register).

Hope this helps someone out there!

1 Like