#### Archived

This topic is now archived and is closed to further replies.

# Parallel Port Access Under Win32 C++

This topic is 5619 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Platform: PC Windows 32 Application Language: C++ Compiler: MSVC++ 6.0 API:DirectX 7.0 I just ran into a problem with a project of mine, hope someone can help. I am writing a game that will make use of an electronic device that is connected to the parallel port. I needed to be able to use Data lines 0-7 as sources of +5v to drive some led''s. This was no problem for me while testing under a console application as I used the _outp(0x378, [int/hex value]) function to control the data lines. Upon moving the program to a win32/directX environment I was dismayed that this function causes the window to collapse and the application to hault. I assume that this is because the function only works under DOS and console apps. So my question is, how can I gain control of the data lines of the parallel port under a win32 app. Does DirectX contain contexts for a printer device? I know that I can create different apps using the wizard in MsvC++ but i can''t throw away the rest of my game. This is how it worked under Console app: #include <dos.h> #include <stdio.h> #include <conio.h> #define DATA 0x378 // Address of parallel port void main() { _outp(DATA, 10); // outputs a binary 10 on data lines // under Borland this function is // outport(DATA, [int/hex value]) } so the above would put 00001010 on the data lines and drive tha anode side of my 8bar led display with +5v.

##### Share on other sites
It''s likely that a console prog would collapse on NT as well, due to more robust restrictions on accessing ring0 from ring3. Look into GDI for printer device contexts. Also take a look at the winio dll at internals.com for accessing the parallel port. In the worse case, you might have to write a small device driver of somekind.

##### Share on other sites
You have to write a driver

##### Share on other sites
I´m having the exact same problem zenassem. Magmai, How do I write a driver? Can you point me to any link? Thanks!

##### Share on other sites
Writing a device driver means getting the Device Driver Kit specific to the target platform - W95, W98, WME, WNT, W2K, WXP - each of them are large, but not as large as the PSDK. I have a copy of the DDK for W2K. It even comes with a compiler! cl.exe because you can''t use the MSVC compiler. Most of the DDK consists of special headers for kernel mode. There are a couple of interesting newsgroups related to the topic.

But you don''t need to do any of that. The winio dll will let you access the parallel port with a command as simple as "GetPortVal(0x378,&dwPortVal,4);". Internals.com

##### Share on other sites
IIRC, in NT you can access the parallel port using CreateFile("\\\\.\\LPT",...). Look on MSDN.

##### Share on other sites
You can probably use the parallellport pretty much as you would a COM-port.

CreateFile("LPT1" . . . . .) or whatever port it is.
GetCommState(. . .)
SetCommState(. . .)
WriteFile(. . . .)
CloseHandle(. . . .)

Just fill in the dots with a trip to MSDN.

##### Share on other sites
quote:
Original post by Anonymous Poster
You can probably use the parallellport pretty much as you would a COM-port.

CreateFile("LPT1" . . . . .) or whatever port it is.
GetCommState(. . .)
SetCommState(. . .)
WriteFile(. . . .)
CloseHandle(. . . .)

Man, wouldn''t that be nice?
Try searching MSDN for it...

quote:
Anonymous Poster
IIRC, in NT you can access the parallel port using CreateFile("\\\\.\\LPT",...). Look on MSDN.

Did a quick search, hoping you were right... 0 hits

The only information I found on MSDN last time I checked for this, was info about making a driver to do what you needed. From what I''ve gathered, you have to handle the ISR for the port, since parallel transfers are unbuffered (unlike serial).
I wasn''t that hot on the project, and dropped it when it started to get hard...

I''d be happy to hear (and see) contrary information...

Another alternative, is to search for an NT driver that provides a serial-like interface.

##### Share on other sites
I´ve found a driver on the the internet for free. The webpage is: http://www.driverlinx.com//DownLoad/DLPortIO.htm?ID=1027728744560 . I haven´t tested it yet with the multimeter, but I´m pretty sure it works. Oh! I tested it with a DX App (making a couple of functions calls inside the main loop) and the program didn´t crash at all.

##### Share on other sites
Hey guys/gals
Thanks for the replies. I will check out LessBread's suggestion as well as Ignacio's link today. I did check out the MSDN disks, but I didn't find anything promising with regard to LPT1, it seems that I would be better off using the serial(COM) port intstead. I tried using "outfile" and this did send a print job , that coincidentally errored, to the default printer device (Generic IBM Text Only). This obviously did not work since the driver is not compatible and I haven't done anything with the electronics to send back as ready to RCV or ACK signal.

for the time being I decided to Write [Virtual Parallel Port Emulator and 10-bar Led] Classes. Hence my next question. the _outp() function was great because it converted my decimal "decval" to binary and set the corresponding bits on LPT1. So as 'decval' increased the the function would automatically give me a binary counting clock on the LED display.
How should I model these objects in my class, and how can i convert the decimal index to binary for the pins.

assume:
int decvalue=0 ; decimal value initalized will increment to 128

for simplicity lets say that the Class acts more like a struct and everything is public and assume that other variables are global. My first bad idea was to model the data ports in array; short int port[8] = {0,0,0,0,0,0,0,0} // data line 0-7 set to off

Then I index into this array to change the bits, which eventually drives the (sprites showing the value of the ports) on the display. This obviously takes more memory than bit fields
, but it works. The problem is: decvalue will be a decimal number staring at 0 and incrementing to 128. What is the best method to take the decimal value and change the corresponding array elements to give the binary equivalent. I have a brute force method, but it just looks ugly.

It contains ints that hold the binary place holders.
eg. 1,2,4,8,16,32,64,128
I use an 'if else' to first check if decval is = to one of these
then set the bit that corresponds to the index. Next I look into the array checking to see if decval is less than each place holder. eg. if (decval<128){}; if(decval<64) etc. and when this is true I perform a division, set the current bit, and repeat this process until the decval = 0. (There are other steps like adding the values and such but you get the idea).

There has to be an easier way. Should I do a recursive solution? Is there a function that can handle this for me? Is my structure completely wrong? Should I use bit fields? If so, How can access and change each bit in the field to correspond to decval?

[Please dont' suggest that I create 128 arrays to hold the binary equivalent] My firend actually suggested this.

[edited by - zenassem on July 29, 2002 9:30:29 AM]

##### Share on other sites
Sorry Double post!

[edited by - zenassem on July 29, 2002 9:22:50 AM]

##### Share on other sites
Um, it seems to me that the decimal values only exist in the source code. Once compiled its all binary.

##### Share on other sites

My main issue is not with why _outp() works. I am now emulating a Parallel port and Led display. In the source code I want to represent the 8 data lines of the port by an array. eg pinoutarray[8]. now the diplay function looks at this array to decide which sprites(images) it needs to display. for example if the ellements in the pinoutarray[8] were = to {0,0,1,0,0,1,1,1}; then the display would turn off the bitmap images for pin 0,1,3,4 and turn on the bitmap images for pins 2,5,6,7. This all works. but what i want to do is to create a display of a counting binary clock. eg.
00000000
00000001
00000010
00000011 etc.

To count up to 128 I have a decimal value int named "decval"
"decval" in a loop and counts form 0 to 128. I need some way to have the array elements correspond to "decval" value. so if decval==7 the array elements in pinoutarray[8] would look like this. 00000111 {note i am listing the elements for 7 to 0 so it will match a binary representation}

 My thanks to lessbreead didn't look sincere, and read back it sounded as though I was frustrated.

[edited by - zenassem on July 29, 2002 10:43:09 AM]

##### Share on other sites
Ok. That makes more sense! Somehow I thought that you wanted to send that data to the port. Now I see that you want to send it to the gui.

Does the display really need to use individual sprites? I'm thinking that it might be easier to just convert the decimal number to a string representing the binary value and then send that to the display. If you use a fixed sized font the "numbers" will remain aligned.

Alternatively - since there are only two binary digits, you only need to store two sprites - one for 0 and one for 1. Then just check each bit of the byte to see if it's set and if it is display 1 in that slot and 0 otherwise. Too bad you have to go up to 128. If you only needed to go to 127 you could bypass checking the msb.

// Edit
quote:

My thanks to lessbreead didn't look sincere, and read back it sounded as though I was frustrated.

Don't worry about it. I have much thicker skin that that.

[edited by - lessbread on July 29, 2002 10:57:46 AM]

##### Share on other sites
yes, it does need to use sprites(blitter objects) because the program graphically depicts the parallel port and the 8bar Led. It graphically shows the pins that are on and the lights up the 8bar led. I don''t have to go up to 128. 127 is fine. But it really isn''t a big deal as 128 is represented pinoutarray[8]={0,0,0,0,0,0,0,1}; [note: this time i am showing the bits as the y would be initalized intto the array.] and so therefore this is an easy test case as you can see from my earliesr post. I have ints that represent the powers. If dec==128 then i just turn bit7 on. The hard part is that the conversions must be done real time. I cannot just have 128 arrays. Because that would just be ugly and brute. Also i will need to be able to run other patterns other than just counting up.

##### Share on other sites
Wouldn''t this do the job for decimal to binary conversion? Or is there something wrong with this method I don''t know about?

Don''t laugh at this code too much, hehe.

  #include <iostream>using std::cout;using std::endl;int main(){	int test=116;	int binaryValue[8];	cout << "Bit position" << endl;	cout << "7 " << "6 " << "5 " << "4 " << "3 " 		<< "2 " << "1 " << "0 " << endl << 		"======================================" << endl; 	for (int i=0; i<=7; i++)	{		(test & (1 << i)) ? binaryValue[i] = 1 : binaryValue[i] = 0;	}	for(i=7; i>=0; i--)	{		cout << binaryValue[i] << " ";	}	cout << endl;	if (test & 128)		cout << "Test and 128" << endl << endl;	return 0;}

##### Share on other sites
Well the real time requirement throws things off, but I think it better to first get something working and then work on improving the speed.

I don''t think you''ll need 127 arrays. This is what I would do

First blit the background for all 8 slots
[0|0|0|0|0|0|0|0]

This sprite should cover the entire range and it should be all zeros. Then I would check each bit of the data value to see if it was set and if it was I would blit a smaller sprite [1] in the corresponding slot. (note that I''m using [] to represent a square sprite not an array)

if ( data & 1 << 8 ) { blit [1] in slot 8 } // else blit nothing
if ( data & 1 << 7 ) { blit [1] in slot 7 } // else blit nothing
if ( data & 1 << 6 ) { blit [1] in slot 6 } // else blit nothing
if ( data & 1 << 5 ) { blit [1] in slot 5 } // else blit nothing
...

If you think the conditional check will cost too much, an alternative possibility is to use the result from the and as an index into an array storing two sprites - [0],[1] -

sprite[0] -> [0]
sprite[1] -> [1]

for each slot
blit(slot, sprite[data & 1 << slot])

But i think it more likely that the blit will cost more than the conditional - the first example is worse case 9 blits, the second example is always 9 blits.

If you can only afford one blit - then you''re gonna need 127 sprites. Perhaps you can build them at runtime using one of these approaches and then just use the data value as an index into the sprite array.

Am I in the ball park here?

##### Share on other sites

I think you are in the ball park. I haven''t looked fully through Anon. poster''s code yet. The only part I am confused about with your solution is "data & 1". I am not sure how exactly this works. Is data a decimal number? Just to clarify, I am not concerned about how many times I need to blit. In fact, that''s how my code does it the way it is. I check the array for each bit [index] in a for loop. If the value is 1 I blit. If 0 I hide the sprite. I have no problem with this.
My problem came from how do I set the bits in the array from looking at the decimal #.

example my decimal number (data) is 10.
I need to take the number 10. and now index into the array to set the bits, necessary. [I know how to index into an array. I know how to set any particular bits. I know how to read these bits into the display. !!!!The thing I was unsure of is how to look at "data", then flip the corresponding binary bits!!!. in this example the array would be

pinoutarray[0]=0; //in the actual code this is in an indexed
pinoutarray[1]=1; // for loop
pinoutarray[2]=0;
pinoutarray[3]=1;
//all the rest would be 0

When data increments to 11 pinoutarray[0]=1 as well; but I need an algorithm that will be able to look at the decimal value, then know which bits to set high based on that value. This algorithm needs to work for every possible # from 0 to 128.

In other words I DON''T want to do this: (pseudo code)

if data=0 then pinoutarray[]={0,0,0,0,0,0,0,0}
if data=1 then pinoutarray[]={1,0,0,0,0,0,0,0}
if data=2 then pinoutarray[]={0,1,0,0,0,0,0,0}
if data=3 then pinoutarray[]={1,1,0,0,0,0,0,0}
if data=4 then pinoutarray[]={0,0,1,0,0,0,0,0}
...
if data=127 then pinoutarray[]={1,1,1,1,1,1,1,0}
if data=128 then pinoutarray[]={0,0,0,0,0,0,0,1}

##### Share on other sites
Ok. That's good to hear.

What I call "data" is your number 10 - it's just an integer value - you could use an int or a char. What ever value corresponds with to the data that you want to display.

What that code does is check each bit of the char to see if it's set. It does that using a bitwise AND - here's a cut and paste from some old notes of mine

// - snip
AND &- operates like a 2 bit truth table- if either bit is zero, yield bit is zero too- both bits must be one for the yield bit to be one- x & 0 = 0 | x & 1 = x  0011& 0101  ----  0001	using hex simplifies - to wit0x80 = 100000000x40 = 010000000x20 = 001000000x10 = 000100000x08 = 000010000x04 = 000001000x02 = 000000100x01 = 00000001// - snip1 << slot - left shift a bit into "slot"0x80 == 10000000 == 1 << 7 == 1280x40 == 01000000 == 1 << 6 ==  640x20 == 00100000 == 1 << 5 ==  32 0x10 == 00010000 == 1 << 4 ==  160x08 == 00001000 == 1 << 3 ==   80x04 == 00000100 == 1 << 2 ==   40x02 == 00000010 == 1 << 1 ==   2 0x01 == 00000001 == 1 << 0 ==   1

You can save a bit of time by using the hex values explicitly instead of shifting 1 left X number of slots.

Note that the AND returns 0 or 1 - and that those two values correspond with false and true respectively. So if the bit is set, the AND returns 1 indicating that the [1] sprite should be blit - else the AND returned 0 and nothing should be done since the back ground has already been filled with zeros due to the first blit.

The approach should actually be more like - blit the "zero" background to a back buffer, then blit each slot with [1] as needed, then blit the back buffer to the front buffer.

What I'm saying is that the data number itself carries the bit pattern with it.

Decimal 53 Binary 00110101 - from the look of those arrays it appears that you have the bits in reverse order so that 53 would be 10101100. That won't make a difference as far as the logic of whether a given bit in the number is set or not. It does mean that you'll have to take extra care to keep the display offsets in proper corresondence with each bit.

slot  76543210(53)  00110101(127) 01111111slot  01234567(53)  10101100(127) 11111110

You don't need to do that array stuff, because the index value/data value contains the bit pattern.

[edited by - lessbread on July 29, 2002 1:09:43 PM]

##### Share on other sites
Thanks sooo much! I finally understand what you mean. I didn''t know how to look at the actual bits that make up a decimal number, nor how to express the question, since I didn''t know that this could be done. Sorry for putting you through all of that. I appreciate you staying with me and answering my question. In retrospect, it must have been unnerving for you to figure out why I was having any problem to begin with.

##### Share on other sites
Not a problem. I''m glad you didn''t find all that condescending or anything. After I posted it I wondered if you might already have known about bit setting and retrieving, but I guess they don''t teach bitwise stuff that much any more. I didn''t find it unnerving at all.

Here is the rest of my old notes cleaned up a little so you can have a reference if you need it.

  BITWISE OPS : merging ops require data items to be of the same type (ie. have the same number of bits)operates on each corresponding bit in each data item in turn to yield a third bit in the resulting data itemeach bit is independent of the others - there is no arithmetical carry over from bit column to bit columnAND &- operates like a 2 bit truth table- if either bit is zero, yield bit is zero too- both bits must be one for the yield bit to be one   0011 & 0101   ----   0001	   FFTT  & FTFT   ----   FFFTXOR ^- bitwise exclusive OR- returns 1 when either bit but not both are 1- an XOR applied twice yields the original operand   0011 ^ 0101   ----   0110   FFTT ^ FTFT   ----   FTTFOR |- two bits ORed yield 1 if either or both bits are 1 and 0 if both bits are 0- used to combine bits from different variables into a single variable   0011 | 0101   ----   0111   FFTT | FTFT   ----   FTTTBITKEYX 0011Y 0101op==== & 0001^ 0110| 0111BITKEYX FFTTY FTFTop==== & FFFT^ FTTF| FTTT0x80 == 10000000 == 1 << 7 == 1280x40 == 01000000 == 1 << 6 ==  640x20 == 00100000 == 1 << 5 ==  32 0x10 == 00010000 == 1 << 4 ==  160x08 == 00001000 == 1 << 3 ==   80x04 == 00000100 == 1 << 2 ==   40x02 == 00000010 == 1 << 1 ==   2 0x01 == 00000001 == 1 << 0 ==   1BITWISE LEFT <<- always shifts in 0 bits from the right discarding left most bits- each bit shifted is equivalent to multiplying by 2- so shifting left 3 bits is like muliplying by 8intVar << x (places)RIGHT SHIFT >>- moves each bit in operand to the right the indicated number of places- shifting right one bit same as dividing operand by 2intVar >> x (places)- zeros are shifted from the left and the right most bit disappear- except in the case of signed types where a 1 in the left most bit indicates a negative number- 1''s are shifted in to preserve signif the signed bit is set in a signed operand, right shifts will shift 1''s in from the leftBITWISE COMPLEMENT ~ (unary)- reverses each bit- complementing a number twice returns the orginal number

• ### Forum Statistics

• Total Topics
628730
• Total Posts
2984427

• 25
• 11
• 10
• 16
• 14