From Display-Corner
Jump to: navigation, search




        parPulse(portAddr, pulseVal, afterVal, valMask, pulseTi, isTrigger);

        parPulse([portAddr,] pulseVal, afterVal, valMask, pulseTi);
  val = parPulse([portAddr]);

        parPulse(0);   (only since v1.1)
portAddrDecimal 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')).
0Since v1.1, parPulse(0) will do nothing but print the version number. Do not specify an output parameter when calling parPulse(0).
pulseValOutput value during the pulse.
afterValOutput value after the pulse.
valMaskBit mask (as decimal value), indicating which output lines of the parallel port will actually be affected when programming pulseVal and afterVal.
pulseTiPulse duration in seconds. Pulse durations longer than 1s will be automatically clamped to 1s 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.)
isTriggerIf 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 the pulse latency. Moreover, with the script execution blocks until the end of the pulse, if not in trigger mode.
valVector 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

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 ResourcesI/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.


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.
Note that just calling parPulse comes with a time overhead of about 25µs (Intel Core-i5-2500 Win7 PC), most of which is probably caused by the Matlab MEX layer. Within parPulse itself, overhead is minimized by keeping things initialized between the calls. Wrong! 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).

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)

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.
Personal tools