Help with lptread/porttalk

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
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
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

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

Hope this helps.
Frank Schieber
University of South Dakota


--- In 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
>
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 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
a possible national instruments usb digital i/o is (<$100):
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
and
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/PIC_microcontroller

i'm interested to hear how it turns out -- let me know if you have
more questions!

-erik