Thank you very much Uberi!
Originally the speed was only around 200 Hz, then with just the inpout32.dll loaded it went up to around 8000 Hz and after the procedure addresses pre-fetch it went up to around 15000 Hz (on an old Dell Optiplex 745 running XPpro). This is great! I believe it was the unicode issue that I had.
Below is the code that I've put together. Both ouput and input pins can be accessed individually (or all at once). See the Example Usage section for more details.
; The Pins of Parallel Port DB25 connector, When Looking at the Female Connector on a PC:
;
; \--------------------------------------------------------------------/
; \--13---12---11---10----9----8----7----6----5----4----3----2----1--/
; \----------------------------------------------------------------/
; \--25---24---23---22---21---20---19---18---17---16---15---14---/
; \------------------------------------------------------------/
;
; Output pins: 2, 3, 4, 5, 6, 7, 8, 9
; Input pins: 10, 11, 12, 13, 15
; Ground pins: 18, 19, 20, 21, 22, 23, 24, 25
; Control pins: 1, 14, 16, 17
;
; Bidirectional mode is not enabled (output pins are output pins, not bi-directional).
; Control pins are not used/needed for this utility
;
; In the code:
; value 0 denotes voltage level Low
; value 1 denotes voltage level High
;
;==============================================================================
;The parallel port is nearly always LPT1
OutputPortAddress = 0x378 ;LPT1
InputPortAddress = 0x379 ;LPT1
ControlPortAddress = 0x37A ;LPT1
;OutputPortAddress = 0x278 ;LPT2
;InputPortAddress = 0x279 ;LPT2
;ControlPortAddress = 0x27A ;LPT2
;==============================================================================
;seach for the file inpout32.dll from three locations:
; sub-folder \tools under the folder where the script is
; the same folder where the script is
; \windows folder
dllPath = %A_ScriptDir%\tools\inpout32.dll
IfNotExist, %dllPath%
dllPath = %A_ScriptDir%\inpout32.dll
IfNotExist, %dllPath%
dllPath = %A_WinDir%\inpout32.dll
IfNotExist, %dllPath%
{
msg := "First copy the inpout32.dll library file to one of the following folders:" "`n`n"
msg := msg " - " A_ScriptDir "\tools\" "`n"
msg := msg " - " A_ScriptDir "\" "`n"
msg := msg " - " A_WinDir "\" "`n`n"
msg := msg "Exit with no actions taken." "`n"
msgbox % msg
ExitApp
}
;==============================================================================
; *** Thanks to Uberi @ AutoHotkey Forum! ***
UPtr := A_PtrSize ? "UPtr" : "UInt", AStr := A_IsUnicode ? "AStr" : "Str"
;load the module into memory
;hModule := DllCall("LoadLibrary", "Str", dllPath, "Ptr")
hModule := DllCall("LoadLibrary","Str",DllPath,UPtr)
;and read the address of procedures
OutProc := DllCall("GetProcAddress",UPtr,hModule,AStr,"Out32",UPtr)
InpProc := DllCall("GetProcAddress",UPtr,hModule,AStr,"Inp32",UPtr)
;==============================================================================
;read in the initial state of the ouput port
OutputPortData := DllCall(InpProc,int,OutputPortAddress)
;==============================================================================
;START OF EXAMPLE USAGE
;set all eight output pins low
WriteOutputByte(0)
msgbox All output pins should be Low
;set all eight output pins high
WriteOutputByte(255)
msgbox All output pins should be High
;set the pin 3 to be low (the pins 2 to 9 can be adressed individually like this)
WritePin(3,0)
msgbox output pin3 should be Low
;set pin 3 to be high (the pins 2 to 9 can be adressed individually like this)
WritePin(3,1)
msgbox output pin3 should be High
;read in the state of all the five input pins
gosub ReadInputPins
;and then show their state
msg =
(
These inputs are normally all high unless connected to ground.`n
Pin 10 State = %Pin10State%
Pin 11 State = %Pin11State%
Pin 12 State = %Pin12State%
Pin 13 State = %Pin13State%
Pin 15 State = %Pin15State%
)
msgbox, % msg
;read in the state of an individual pin (here pin 11) and show it
PinToRead = 11
msg := ReadInputPin(PinToRead)
msgbox, % "Pin " PinToRead " state is: " msg
;test a High/low loop 3000 rounds and show the result
CycleCount = 3000
msg := TestOutputFrequency(CycleCount)
msgbox, % "Frequency as tested by " CycleCount " cycles is: " msg
;END OF EXAMPLE USAGE
goto ByeBye
;------------------------------------------------------------------------------
WriteOutputByte(OutputPortData)
{
Global OutputPortAddress
Global OutProc
DllCall(OutProc,int,OutputPortAddress,int,OutputPortData)
}
;------------------------------------------------------------------------------
WritePin(PinNumber,PinValue)
{
Global OutputPortData
Global OutputPortAddress
Global OutputPortData
Global InpProc
Global OutProc
ormask := 2 ** (PinNumber - 2)
andmask := 255 - ormask
OutputPortData := DllCall(InpProc,int,OutputPortAddress)
if(PinValue=0)
{
OutputPortData := OutputPortData & andmask
}
else
{
OutputPortData := OutputPortData | ormask
}
DllCall(OutProc,int,OutputPortAddress,int,OutputPortData)
}
;------------------------------------------------------------------------------
TestOutputFrequency(loopcount)
{
Global OutputPortData
Global OutputPortAddress
Global OutProc
thistime = %A_TickCount%
loop, %loopcount%
{
OutputPortData = 0
DllCall(OutProc,int,OutputPortAddress,int,OutputPortData)
OutputPortData = 255
DllCall(OutProc,int,OutputPortAddress,int,OutputPortData)
}
thistime := (A_TickCount - thistime) / 1000 ;secons
frequency := loopcount / thistime /1000 ;in kHx
return % frequency " kHz"
}
;------------------------------------------------------------------------------
ReadInputPins:
InputData := DllCall(InpProc,int,InputPortAddress)
Pin10State := 0 < (InputData & 64)
Pin11State := 0 = (InputData & 128) ; no error, this one is inverted by hardware
Pin12State := 0 < (InputData & 32)
Pin13State := 0 < (InputData & 16)
Pin15State := 0 < (InputData & 8)
return
;------------------------------------------------------------------------------
ReadInputPin(PinNumber)
{
Global InputPortAddress
Global InpProc
InputData := DllCall(InpProc,int,InputPortAddress)
if(PinNumber = 10)
Return 0 < (InputData & 64)
else if (PinNumber = 11)
Return 0 = (InputData & 128) ; no error, this one is inverted by hardware
else if (PinNumber = 12)
Return 0 < (InputData & 32)
else if (PinNumber = 13)
Return 0 < (InputData & 16)
else if (PinNumber = 15)
Return 0 < (InputData & 8)
else
{
Msgbox, Only pins 10, 11, 12, 13, and 15 are input pins.
Return -1
}
}
;------------------------------------------------------------------------------
ByeBye:
;unload the module
DllCall("FreeLibrary", "Ptr", hModule)
exitApp
;------------------------------------------------------------------------------
With Best Regards,
Timo