Building OnChange event to listen the parallel port
Friday, April 3rd, 2009 by Pablo RomanoThe parallel port, like most of the hardware, is becoming each day more unknown to the developers. We are getting used to languages that encapsulate all these low level things for us.
Well, recently I found myself needing to wake up an application of mine when the signal of the parallel port changed. This is what I did!
Intro
When I started sketching the behavior of my ParallelPortListener I decided not to go deeper into the OS trying to reach the IRQs. I preferred a code not as optimal but much cleaner and maintainable.
Here is the Source Code.
Code Arrangement
The code is composed of two classes: the ParallelPortListener I told you before and an internal class I called PortAccess whose only task is to call a method, Input(int address), from a dll I’ll talk about later.
ParallelPortListener Class
ParallelPortListener is also composed of many portions of code, each one with a very different purpose:
- The implementation of a Singleton.
This class is a Singleton because I didn’t want simultaneous reads to the port (another possibility was to use the locking mechanisms) - A delegate OnPortChangedHandler
- A public event OnPortChanged where outsiders can subscribe methods matching the signature of OnPortChangedHandler
- A Listener section which contains a Timer that invokes the PortAccess class, and two methods to control this Timer: Start and Stop
Ok, too much introduction, let’s see some code!
Port Access
using System.Runtime.InteropServices; //This namespace contains DllImportAttribute
namespace Utilities
{
public class PortAccess
{
[DllImport("inpout32.dll", EntryPoint = "Out32")]
public static extern void Output(int adress, int value);
[DllImport("inpout32.dll", EntryPoint = "Inp32")]
public static extern int Input(int adress);
}
}
I call the external function “Out32″ in the dll “inpout32.dll” by adding the attribute System.Runtime.InteropServices.DllImport to my method Output.
The external function name is set in EntryPoint, I also had to set the dll name, in this case “inpout32.dll”.
Note: It’s important to remember that inpout32.dll must be on the same location where the application is running.
The best way to be sure you won’t forget is letting VS take care of it.
- Add inpout32.dll to your solution
- Right click on the file and go to properties
- Set “Build Action” to “Content”
- Set “Copy to Output Directory” to “Copy if newer”
ParallelPortListener
Public Properties
The setter is private, only the class can set the value
public int PortValue { get; private set; }
Singleton
private ParallelPortListener() { }
private static readonly ParallelPortListener _instance = new ParallelPortListener();
public static ParallelPortListener Instance { get { return _instance; } }
I like this way of implementing the pattern but there are others
Delegate
Delegate to handle the event
public delegate void PortChangedHandler(int portValue);
Event
And here we have some interesting code, how to create an event.
private event PortChangedHandler _portChanged;
public event PortChangedHandler OnPortChanged
{
add
{
_portChanged += value;
Start();
}
remove
{
_portChanged -= value;
if (_portChanged.GetInvocationList().Length == 0) { Stop(); }
}
}
private void PortChanged()
{
if (_portChanged != null)
{
_portChanged(PortValue);
}
}
Instead of Start I could have used “if (_portChanged.GetInvocationList().Length == 1) { Start(); }”, but I know my method and checking that is more expensive than calling it.
When I call Stop checking is mandatory.
OnPortChanged is where handlers register themselves to observe the port, when someone registers I Start the ParallelPortListener.
The private method PortChanged is called by the Listen method (keep reading) when the PortValue changes.
Listener section
Let’s define two constants: LISTEN_FREQUENCY and PORT_ADDRESS
private const UInt32 LISTEN_FREQUENCY = 100; //100ms private const Int32 PORT_ADDRESS = 889;
The address 889 is for reading the parallel port.
private Timer _timerListen;
//Starts the Timer
private void Start()
{
if (_timerListen == null)
{
_timerListen = new Timer(Listen, null, 0, LISTEN_FREQUENCY);
}
}
//Stops the Timer
private void Stop()
{
if (_timerListen != null)
{
_timerListen.Dispose();
_timerListen = null;
}
}
private void Listen(Object unusedParameter)
{
int newPortValue = PortAccess.Input(PORT_ADDRESS);
if (newPortValue != PortValue) //If the value has changed
{
PortValue = newPortValue; //Update PortValue
PortChanged(); //Notify the listeners
}
}
This Timer is used to Listen the port every LISTEN_FREQUENCY and update PortValue if necessary.
I hope you’ll find this code useful, download it and if you have any doubts or comment feel free to post!
References
How to program a parallel port using c# the way you want
Implementing Singleton in C#
Timer Class
Tags: C#, Delegate, dotnet, Event, Parallel Port, Singleton, Timer

April 16th, 2009 at 2:38 pm
Excellent article! Very complete and neat
April 16th, 2009 at 3:29 pm
I have only one question, i am newbie with Delegates and I would like to see an example showing how to use ParallelPortListener. Thanks a lot in advance
April 17th, 2009 at 10:54 am
Hi Wilman,
Thanks, I’m glad you liked it!
Here is an example, if you have any doubts tell me.
Greetings from the other side of the Rio de la Plata,
Pablo
Example:
class DemoClass
{
public DemoClass()
{
PortListener.ParallelPortListener.Instance.OnPortChanged += OnPortChanged;
}
void OnPortChanged(int portValue)
{
//Do something with portValue
}
}
April 20th, 2009 at 2:30 pm
Pablo,
I have already figured it out myself after trying but thanks a lot for typing it since it will be useful for others I think. The project worked great with this. Go ahead, really nice blog!
September 21st, 2009 at 2:44 am
hello is it listen to lpt pin no 10????????? plz replay soon
September 21st, 2009 at 11:31 am
Hi Niraj,
The code listens all the pins, it translates the binary number to it’s decimal form.
If you only need the 10th pin you can mask the others by doing “bool pinState = (readedNumber & (int)Math.Pow(2, 6)) != 0;” (http://www.ctv.es/pckits/tutorial.html#padr)
Please tell me if this helps or you need more assistance.
October 17th, 2009 at 11:57 am
Excelent article, but I have a question: Does it works with a USB to parallel cable (1284)? I am looking to access the pins of the this port with the cable.
Thank you
October 18th, 2009 at 12:55 pm
Hi Miguel,
I haven’t tried the code with a usb to parallel, I think in the worst case only a change in the PORT_ADDRESS constant will be needed.
Try it and let me know
December 14th, 2009 at 12:17 am
how to deactivate a certain pin?
i know that ‘PortAccess.Output(address, 0)’ is to deactivate all the pins.
December 14th, 2009 at 3:26 pm
Hi Bennyben,
I guess you want to send a 0 to a particular pin, but when you write to the port you must send 1s or 0s to all the others too.
Reading and writing can be done through PortAccess.Input and PortAccess.Output. The latter receives the address and a decimal value that is converted to it’s binary form, where each bit correlates to a pin. Here is a link explaining what you can do with each pin.
http://www.beyondlogic.org/spp/parallel.htm#5
If you want to change the value of one pin first of all you need the value of the others, the ones that don’t change. If you are working with the bi-directional pins you can read the value, if you are using the write-only ones you must keep the value in your application.
Let’s suppose the value is 11011011 = 219 dec and you want to send a 0 to the 4th pin (bit 3), then you should make a mask that has a 0 in that position, 1s in all the others and make a bitwise and (&) with the current value. Here is an example:
int currentValue = 91; //01011011
int mask = 255 - (int)Math.Pow(2, 3); //11111111 - 1000 = 11110111
int newValue = currentValue & mask; //01110111 & 11011011 = 01010011
If you want to send a 1 to a pin you should make a mask with 1 in that pin, 0s in all the others and make a bitwise or (|) with the current value.
Please tell me if this helps or you need more assistance.
January 8th, 2010 at 3:23 pm
I have my code working but I have a question on the pins
I am trying to receive some inputs from the port.
I know the 8 data pins are used for output
I can receive the input of the 5 status pins but for some reason I cant find a way to receive input data from the 4 control pins. I though they were I/O. if so , what am I doing wrong?
January 12th, 2010 at 3:12 pm
got it to work