# Help with lptread/porttalk

**URL:** <https://psychtoolbox.discourse.group/t/help-with-lptread-porttalk/1684>\
**Category:** Uncategorized\
**Created:** [June 26, 2007, 12:04pm UTC](https://psychtoolbox.discourse.group/t/help-with-lptread-porttalk/1684 "2007-06-26T12:04:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Allen\_Ingling](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Allen\_Ingling](https://psychtoolbox.discourse.group/u/Allen_Ingling)\
**Post date:** [June 26, 2007, 12:04pm UTC](https://psychtoolbox.discourse.group/t/help-with-lptread-porttalk/1684/1 "2007-06-26T12:04:56Z")

</div>

Hi,  
  
I inherited a response box, replete with hand and foot-response pedals, but without a driver, and I'm keen to try and use it for a new study on an XP machine. It connects via a 25 pin parallel port, but as yet, I've not been able to get it working. I installed and, after a few tries, got the porttalk/lpwrite/lpread files compiled as per the excellent instructions in Andreas and Erik's original posts from mid last year (see msg #4851). Having problems reading data from the box though. In particular, I think I'm having difficulty finding the right port param for the lptread fx.  
  
Function value = lptread(port)  
  
% Arguments:  
% port - double Port address (e.g., 889 = 0x1 + 0x378 for status register of LPT1  
% on many machines, which corresponds to pins 10, 11, 12, 13, and 15 of a DB25  
% parallel port -- note pin 11 is hardware inverted!)  
%  
% Examples:  
% val = lptread(1+hex2dec(0x378));  
%  
% Author: Erik Flister, UCSD, 2006. Adapted from Andreas Widmann.  
  
  
although 378 seems to be the correct resource signing for my parallel port (as per the eg code above), I get the same value returned regardless of which buttons are being pushed on the box. I'm also really not sure what the hex values are, or even which pins I should be reading from (was planning on trying to find this out via trial and error...)  
  
Does anyone have any working example code they could send? Or ideas on what I might be having problems with? The box does work correctly on another machine, but with installed software and the original programmer long gone... Should also add that I have Matlab's DAQ toolbox, but wasn't having any luck reading a response from the parallel port with that either - again, sample scripts or knowhow would be much appreciated!  
  
Many thanks.  
  
Chris

---

<div class="post-metadata">

**Author:** ![frankschieber](https://avatars.discourse-cdn.com/v4/letter/f/278dde/32.png) [@frankschieber](https://psychtoolbox.discourse.group/u/frankschieber)\
**Post date:** [June 26, 2007, 3:56pm UTC](https://psychtoolbox.discourse.group/t/help-with-lptread-porttalk/1684/2 "2007-06-26T15:56:05Z")

</div>

Greetings Chris.  
  
Last semester I taught a course in which my students learned how to   
use MATLAB and Cogent 2000 to implement near real-time cognitive   
psychology experiments. As part of the course, we built a button   
box that interfaced to our Windows XP legacy printer port (LPT1).   
The syllabus for that course can be found at:  
[http://www.usd.edu/~schieber/psy770/psyc770-syllabus1.htm](http://www.usd.edu/~schieber/psy770/psyc770-syllabus1.htm)  
For the class scheduled for 3/29 you will find a link to an M-file   
for reading this buttonbox via the LPT1 port (i.e.,readButtonbox.m).  
[http://www.usd.edu/~schieber/psyc770/m-files/readButtonbox.m](http://www.usd.edu/~schieber/psyc770/m-files/readButtonbox.m)  
  
This MATLAB function does NOT use the PortTalk driver but can be   
easily modified to work with PortTalk. To do so: (1) comment-out   
the if(cogent.io.status ~= 0)...end code that checks for the io32   
driver that we use (instead of PortTalk), and (2) replace   
the "response = uint8( inp(address) )" command with something   
like "response = uint8( lptread(address) )".  
  
Note that the value returned from reading the LPT1 status port is   
coerced into 8-bit unsigned integer format by the 'uint8' function.   
This allows you to then use the MATLAB bitget() function to test the   
logic level of the LPT1 status port on a bit-wise basis (see the   
readButtonbox.m code and comments for additional details).  
  
For example:  
  
%initialize address of LPT1 status port  
address = hex2dec('379'); %standard status register addr  
%  
%read current state of input lines connected to LPT1 status port  
response = uint8( lptread(address) ); %using your lptread() cmd  
%  
%test to see if LPT1 pin #15 is active (i.e., grounded to logic 0)  
%Note: pin-15 input maps to LPT1 status port bit #4 (in MATLAB-speak)  
if( bitget(response,4)== 0)  
 disp('Pin #15 is at logic state 0 (Active)')  
else  
 disp('Pin #15 is at logic state 1 (Inactive)')  
end  
  
If you have more difficulties with PortTalk, you may want to   
consider using our MATLAB port I/O extensions for Windows that use   
another freeware driver. For more info see:  
[http://www.usd.edu/~schieber/psyc770/IO32.html](http://www.usd.edu/~schieber/psyc770/IO32.html)  
  
Hope this helps.  
Frank Schieber  
University of South Dakota  
  
  
--- In [psychtoolbox@yahoogroups.com](mailto:psychtoolbox@yahoogroups.com), "Christopher Hatherly"   
\<Christopher.Hatherly@...\> wrote:  

> \>  
> \> Hi,  
> \>   
> \> I inherited a response box, replete with hand and foot-response

pedals, but without a driver, and I'm keen to try and use it for a   
new study on an XP machine. It connects via a 25 pin parallel port,   
but as yet, I've not been able to get it working. I installed and,   
after a few tries, got the porttalk/lpwrite/lpread files compiled as   
per the excellent instructions in Andreas and Erik's original posts   
from mid last year (see msg #4851). Having problems reading data   
from the box though. In particular, I think I'm having difficulty   
finding the right port param for the lptread fx.  

> \>   
> \> Function value = lptread(port)  
> \>   
> \> % Arguments:  
> \> % port - double Port address (e.g., 889 = 0x1 + 0x378 for status

register of LPT1  

> \> % on many machines, which corresponds to pins 10, 11, 12, 13, and

15 of a DB25  

> \> % parallel port -- note pin 11 is hardware inverted!)  
> \> %  
> \> % Examples:  
> \> % val = lptread(1+hex2dec(0x378));  
> \> %  
> \> % Author: Erik Flister, UCSD, 2006. Adapted from Andreas Widmann.  
> \>   
> \>   
> \> although 378 seems to be the correct resource signing for my

parallel port (as per the eg code above), I get the same value   
returned regardless of which buttons are being pushed on the box.   
I'm also really not sure what the hex values are, or even which pins   
I should be reading from (was planning on trying to find this out   
via trial and error...)  

> \>   
> \> Does anyone have any working example code they could send? Or

ideas on what I might be having problems with? The box does work   
correctly on another machine, but with installed software and the   
original programmer long gone... Should also add that I have   
Matlab's DAQ toolbox, but wasn't having any luck reading a response   
from the parallel port with that either - again, sample scripts or   
knowhow would be much appreciated!  

> \>   
> \> Many thanks.  
> \>   
> \> Chris  
> \>

---

<div class="post-metadata">

**Author:** ![e\_flister](https://avatars.discourse-cdn.com/v4/letter/e/e36b37/32.png) [@e\_flister](https://psychtoolbox.discourse.group/u/e_flister)\
**Post date:** [June 27, 2007, 1:07am UTC](https://psychtoolbox.discourse.group/t/help-with-lptread-porttalk/1684/3 "2007-06-27T01:07:42Z")

</div>

hi chris-  
i'm happy to help if frank's method doesn't work for you or you prefer  
to use our porttalk solution and still haven't got it working.  
  
some thoughts:  
see [http://www.beyondlogic.org/spp/parallel.htm](http://www.beyondlogic.org/spp/parallel.htm) for a list of the pins  
and their associated register/bit locations and whether they are  
inverted. note that the "status register" pins (input) have the  
address offset of one, and the "data register" pins (output) have no  
address offset. the "control register" is supposedly bidirectional  
(address offset of two), but i've had issues getting it to work for  
input on some machines.  
  
if you aren't seeing the bits for the status (input) pins flip when  
you think you should, try indexing them from the other direction (bit  
8 becomes bit 1, bit 7 becomes bit 2, etc.) it's easy to get these  
backwards. i use matlab's dec2bin(val,8) function to convert the  
decimal value returned by lptread() into a readout of the bit values  
and just look at them all. when using dec2bin() be sure to pass a  
second argument of 8 so that leading zeros don't get left off -- i had  
a bug for a while that had to do with the bits shifting their  
positions as the number of leading zeros changed! frank's  
uint8/bitget method works fine too.  
  
to read input on the status pins, loop the following code and allow it  
to print output to the screen while you toggle one of the status pin  
states:   
dec2bin(lptread(1+hex2dec('378')),8)  
  
this should work fine for you if you open your device manager (right  
click "my computer", choose "properties", choose "hardware", choose  
"device manager", choose "Ports (COM&LPT)", choose the LPT port,  
choose "resources", check "I/O range") and the address listed there is  
"0378-037F". if you have some other address, replace '378' with the  
address listed for the beginning of the range. NOTE THE "1+" BEFORE  
"hex2dec('378')"! this is what is offsetting the address into the  
status register so you can see the input pins. from your message, i  
think you are trying to read input from the base address (378), which  
will only let you see the \*output\* pins on the data register -- since  
you're not writing to these, you're not seeing anything change. if  
the base address is 378, you need to be reading from 379 (that's hex  
-- it's 889 in decimal -- since lptread and lptwrite expect the  
address in decimal, we use the hex2dec() to do the conversion). only  
use 378 to \*write\* some output to the data pins.  
  
note that the state of the pins isn't defined on startup/reboot, and  
windows takes the liberty of flipping those bits to check for  
equipment at seemingly random unpredictable times (usually limited to  
shortly after reboot). there doesn't seem to be any way to lock the  
OS or other programs out of messing with your parallel port while you  
want to use it. one strategy is to frequently rewrite your output pin  
value, even if you don't think it should have changed, in case some  
other process flips it while you're not looking. some of the flips  
can be alleviated by setting the following registry key:  
[HKEY\_LOCAL\_MACHINE\SYSTEM\CurrentControlSet\Services\Parport\Parameters]  
"DisableWarmPoll"=dword:00000001  
  
but this doesn't seem to completely solve the problem. so if you have  
external equipment that you don't want affected by these flips, the  
parallel port may not be the best choice. a (for example) national  
instruments usb or pci digital i/o may be better, controlled using  
matlab's data acquisition toolbox. you can use one of these to  
interface the pins on your device to the data acq hardware:  
[http://www.winford.com/products/brk25.php](http://www.winford.com/products/brk25.php)  
a possible national instruments usb digital i/o is (\<$100):  
[http://sine.ni.com/nips/cds/view/p/lang/en/nid/201630](http://sine.ni.com/nips/cds/view/p/lang/en/nid/201630)  
  
finally, if you have the data acquisition toolbox, it's probably  
easier to just use it, rather than porttalk (the one drawback is that  
the data acquisition toolbox can only use ports with the standard  
addresses, so you won't be able to see a pci add-on port). docs are at:  
[http://www.mathworks.com/access/helpdesk/help/toolbox/daq/f11-17968.html#f11-22971](http://www.mathworks.com/access/helpdesk/help/toolbox/daq/f11-17968.html#f11-22971)  
and  
[http://www.mathworks.com/access/helpdesk/help/toolbox/daq/f11-8000.html#f11-22871](http://www.mathworks.com/access/helpdesk/help/toolbox/daq/f11-8000.html#f11-22871)  
(scroll down a paragraph)  
  
oh, it is a remote possibility that although your custom equipment  
interfaces to the computer via the parallel port, it doesn't just  
expose the state of the controls via simple TTL levels on the parallel  
port pins. if the equipment includes some sort of PIC (programmable  
integrated circuit) chip, or something similar, then it might be  
implementing a nonobvious communication protocol.  
[http://en.wikipedia.org/wiki/Programmable\_integrated\_circuit](http://en.wikipedia.org/wiki/Programmable_integrated_circuit)  
[http://en.wikipedia.org/wiki/PIC\_microcontroller](http://en.wikipedia.org/wiki/PIC_microcontroller)  
  
i'm interested to hear how it turns out -- let me know if you have  
more questions!  
  
-erik
