ParPulse: Difference between revisions
mNo edit summary |
m (Fix PP interface link) |
||
Line 69: | Line 69: | ||
The port values are interpreted in binary format where each bit corresponds to one port pin. The lowest significant eight bit (bit0...bit7) correspond to data line 0...7 (pin 2 ... pin 9). These are the regular data lines which can be programmed in perfect synchrony to each other because they are represented in one single hardware register. | The port values are interpreted in binary format where each bit corresponds to one port pin. The lowest significant eight bit (bit0...bit7) correspond to data line 0...7 (pin 2 ... pin 9). These are the regular data lines which can be programmed in perfect synchrony to each other because they are represented in one single hardware register. | ||
Four more bits may be specified (bit8...bit11) which correspond to the pins 1,14,16, and 17, respectively. These bits are represented in another hardware register than the standard lines and are set or reset shortly after the standard lines. Be aware that these are open-collector outputs which do not necessarily have internal pull-ups (see also [ | Four more bits may be specified (bit8...bit11) which correspond to the pins 1,14,16, and 17, respectively. These bits are represented in another hardware register than the standard lines and are set or reset shortly after the standard lines. Be aware that these are open-collector outputs which do not necessarily have internal pull-ups (see also [https://allpinouts.org/pinouts/connectors/parallel/spp-parallel/ Interfacing the standard parallel port]) | ||
=== parPulse version history === | === parPulse version history === |
Latest revision as of 16:24, 5 October 2022
Syntax
parPulse(portAddr); parPulse(portAddr, pulseVal, afterVal, valMask, pulseTi, isTrigger); parPulse([portAddr,] pulseVal, afterVal, valMask, pulseTi); val = parPulse([portAddr]); parPulse(0); (only since v1.1)
portAddr Decimal address of the port's hardware register (see below). If omitted, the previously used address is taken. If such an address was never specified before, 888 is used (=hex2dec('378')). 0 Since v1.1, parPulse(0) will do nothing but print the version number. Do not specify an output parameter when calling parPulse(0). pulseVal Output value during the pulse. afterVal Output value after the pulse. valMask Bit mask (as decimal value), indicating which output lines of the parallel port will actually be affected when programming pulseVal and afterVal. pulseTi Pulse duration in seconds. Pulse durations longer than 1 s will be automatically clamped to 1 s in order to prevent the program from blocking for longer than that. The pulse duration is accurate to ±1µs under Windows XP (in rare cases like 1 out of 10000, +20 µs), and ±4 µs under Windows 7. Of course, these values depend to some extent on the hardware and the installed software.
pulseTi can also be zero, in which case just afterVal is programmed, respecting valMask though. (In the original version (before 09/2016), pulseTi=0 still caused a short pulse to be issued, but only if isTrigger was set.)isTrigger If this flag is specified and set to 1, parPulse() will start the pulse as quickly as possible but uses a more relaxed timing for the pulse duration. More importantly, the function returns instantly after having deferred the pulse termination to some background process. Calling parPulse() before the pulse has been finished is considered an error and will cause the Matlab script to terminate; reading the parallel port can be done anytime though.
If the isTrigger flag is not specified or not set, it is the pulse duration which is maintained most accurately, possibly at the expense of an increased jitter of the pulse latency; moreover, the script execution will block until the end of the pulse.val Vector with two elements, reflecting the current state of port pin 12 and 13, which can be either 0 or 1. The logical state of these pins has to be stable for 6 reads (~32 µs on a Intel Core-i5-2500 Win7 PC) before the function returns, unless this condition is not met after 100 reads, in which case the function returns the result of the last read.
Coding example
parPulse(hex2dec('d030')); % Initialize port parPulse(0,0,255,0); % Set all data lines to 0 parPulse(0,1,255,0); % Set all data lines to 0, except for line 0 which is set to 1 for i=1:50 parPulse(2,1,3,1e-3); % 1ms pulse on data line 0 (negative pulse) % and line 1 (positive pulse) pause(100e-3); % Pause for roughly 100ms end
Port address
For the time being, the port address has to be manually figured out from the list of I/O addresses found in Windows' System Information application (Programs → Accessories → System tools). Look under Hardware Resources → I/O. These adresses might also be listed in the port device properties in the Device Manager.
For example, if there is an entry like
... 0x0000D030-0x000D037 SUNIX 2-Port/Serial / 1-Port Parallel Multi-IO Card OK ...
the address would be hex2dec('d030'), which is 53296.
If there is more than one address listed for what looks like a parallel port device, the correct address has to be found by trial and error. If a wrong address is specified, parPulse() complains either right away or does simply not work because it accesses the wrong registers. Note that parPulse() simply tries to probe the given address for some expected reaction and if the address happens to be wrong, bad things might happen like even crashing the whole system, so save your stuff before searching for the right port address.
Port mode
There is a variety of modes the port can operate in (SPP, ECP, EPP, whatever). Normally, this should not be an issue, because parPulse() initializes the port for output (uni-directional) and disables the interrupt ([portAddr+2]←0x04). Nevertheless, sometimes it might be required to configure the port mode manually (to SPP or Standard or Output only), either in the BIOS or in the Device Manager, if there is such option provided at all.
Timing
When parPulse() is operated in trigger mode (isTrigger==1), the pulse is finished asynchronously with a time resolution of 1ms. Therefore, the specified pulse width will be off by max. one millisecond.
Writing to the port takes about 1.7 µs per call (pulseTi=0). Reading from the port takes about 34 µs per call. And calling the function without doing anything useful takes about 0.9 µs (Intel Core-i5-2500 Win7 PC).Win10 (Intel Core-i5-4570): MATLAB (read/write): typ. 26/8 µs, Octave (read/write): typ. 32/22 µs. Octave being a bit slower reflects that the MEX programming interface is not Octave's preferred interface.
Port output value range
The port values are interpreted in binary format where each bit corresponds to one port pin. The lowest significant eight bit (bit0...bit7) correspond to data line 0...7 (pin 2 ... pin 9). These are the regular data lines which can be programmed in perfect synchrony to each other because they are represented in one single hardware register.
Four more bits may be specified (bit8...bit11) which correspond to the pins 1,14,16, and 17, respectively. These bits are represented in another hardware register than the standard lines and are set or reset shortly after the standard lines. Be aware that these are open-collector outputs which do not necessarily have internal pull-ups (see also Interfacing the standard parallel port)
parPulse version history
v1.1 (16.10.2017)
- Added version output via parPulse(0).
- Removed the initialization step [portAddr+0x402]←0, which was supposed to enforce SPP mode (although only used for port addresses different from 0x?????F??). However, the usefulness of this step is questionable and accessing a memory mapped I/O address which lies outside the allocated address range seems not to be such a great idea either (although the +0x402 address has always been outside the official range).
v1.0 (2013)
- Initial upload.