Updated 2008-03-20 20:26:52 by dec

Extension for LPT access on Windows 98/NT/XP/2k/XP, by ZP Engineering srl [1]. The official page for their Tcl products is [2].

This is a reference page for lpttcl; see also Parallel port for a more general introduction.

Download version 3.0 from [3].

Download version 1.0 from [4].

Commands summary
 .... both versions....

 lpt_getba          returns base address of selected LPT
 lpt_setba <addr>   selects LPT at base address <addr>

 lpt_rddata         returns LPT data register value
 lpt_rdstat         returns LPT status register value
 lpt_rdctrl  	    returns LPT control register value

 lpt_wrdata <val>   writes <val> to LPT data register
 lpt_wrstat <val>   writes <val> to LPT status register
 lpt_wrctrl <val>   writes <val> to LPT control register

 ... only in version 3.0 ....

 lpt_rdreg <offset>        generic register read at (base_address + offset)
 lpt_wrreg <offset> <val>  generic register write at (base_address + offset)

 lpt_setport <id>   selects LPT<id>, where <id> = 1,2,3,...;
 lpt_getport        returns 1,2,....

 (lpt_getba returns -1 if lpt_setport points to a non-existing LPT)
 (lpt_setba now accepts a 32-bit value)


Basic startup code
 console show
 wm withdraw .
 load lpttcl

  set ver [package require lpttcl]

  puts [format "LPTTCL, version %s" $ver]
  puts         "---------------------"
  puts [format "Current port: LPT%d" [lpt_getport]]
  puts [format "Base address: 0x%08X" [lpt_getba]]
  puts " "

  puts [format "Data    register:          0x%02X" [lpt_rdreg 0]]
  puts [format "Status  register:          0x%02X" [lpt_rdreg 1]]
  puts [format "Control register:          0x%02X" [lpt_rdreg 2]]
  puts [format "Extended control register: 0x%02X" [lpt_rdreg 0x402]]

and its output on a console:
 LPTTCL, version 3.0
 Current port: LPT1
 Base address: 0x00000378

 Data    register:          0xAA
 Status  register:          0x78
 Control register:          0x0C
 Extended control register: 0x15


Note that in ver. 3.0 you can now perform a quick autoscan of available LPT ports:
  proc LPTscan {{nmax 8}} {
    for {set i 1} {$i < $nmax} {incr i} {
      lpt_setport $i
      if {[lpt_getba] == -1} {
         puts "LPT$i absent"
         } else {
         puts "LPT$i present"

We made some profiling of access speed (when you insert real code in the loop, it goes slower); note that the test is compatible with both versions.
  proc toggle {num} {
  for {set i 0} {$i < $num} {incr i} {
      lpt_wrdata 0x55
      lpt_wrdata 0xAA

  proc getmaxfreq {{ntimes 10000}} {
    set tt [time {toggle $ntimes}]
    scan $tt %i tt
    set mf [expr (2000 * $ntimes / $tt)] ;# 2 writes, expressed in kHz
    puts "Max frequency is $mf kHz"

Some results (using freewrap 5.4, based on Tcl/tk 8.3.5) using getmaxfreq:

  • laptop, P4 M 1.6 GHz, XP prof.: around 130 kHz
  • desktop, P4 2.4 GHz, XP prof.: around 210 kHz

The old version runs faster (around 2,5 times faster on some PCs!!); furthermore, newer tcl versions are slower. As an example, we measured that 8.3.5 (freewrap) is about 20% faster than 8.4.7 (activestate).

meh: Are there any plans for a Linux version of LPTTCL? If not, can anybody refer me to a page showing how to use applicable LPT pins as 'bits' (on/off state, on sends a small voltage, off sends none)

distatica: meh, if you are referring to individual pin access under Linux, check out the Parapin library located here: http://parapin.sourceforge.net/ If not, please delete this.

dec: meh, I'm currently working on a package that gives access to the parallel port on Linux, Ubuntu 7.10 distribution, it makes use of the ppdev user space driver. It seems to work OK so far. email me at derek dot philip at tesco dot net and I'll forward you the source.

Category Printing | Category Windows