RSS Feed Email Facebook Twitter Stumbleupon Google Bookmark

Controlling the PC Parallel Port (Source Code)

The following is the source code for the Controlling the PC Parallel Port article. Refer to the complete article for implementation details and explanations.

PRN_IO.C


/*
*********************************************************************************************************
* Module     : PRN_IO.C
* Author     : Randy Rasa (http://ee.cleversoul.com/)
* Description: Printer Port I/O Routines
*
* The functions in this module implement a low-level C interface to the standard PC parallel
* printer port, providing up to 12 outputs and 5 inputs.
*
* A standard PC provides for three printer ports, at the following base addresses:
*
*   LPT1 = 0x0378 or 0x03BC
*   LPT2 = 0x0278 or 0x0378
*   LPT3 = 0x0278
*
* This module assumes that LPT1 is at 0x0378.  There's a way to detect this automatically,
* but for simplicity I haven't bothered.  You could also allow an external module to set this
* via a function call, if the port needs to be changed on the fly.
*
* The printer port has three 8-bit registers:
*
*   Data Register (base + 0) ........ outputs
*
*     7 6 5 4 3 2 1 0
*     . . . . . . . *  D0 ........... (pin 2), 1=High, 0=Low (true)
*     . . . . . . * .  D1 ........... (pin 3), 1=High, 0=Low (true)
*     . . . . . * . .  D2 ........... (pin 4), 1=High, 0=Low (true)
*     . . . . * . . .  D3 ........... (pin 5), 1=High, 0=Low (true)
*     . . . * . . . .  D4 ........... (pin 6), 1=High, 0=Low (true)
*     . . * . . . . .  D5 ........... (pin 7), 1=High, 0=Low (true)
*     . * . . . . . .  D6 ........... (pin 8), 1=High, 0=Low (true)
*     * . . . . . . .  D7 ........... (pin 9), 1=High, 0=Low (true)
*
*   Status Register (base + 1) ...... inputs
*
*     7 6 5 4 3 2 1 0
*     . . . . . * * *  Undefined
*     . . . . * . . .  Error ........ (pin 15), high=1, low=0 (true)
*     . . . * . . . .  Selected ..... (pin 13), high=1, low=0 (true)
*     . . * . . . . .  No paper ..... (pin 12), high=1, low=0 (true)
*     . * . . . . . .  Ack .......... (pin 10), high=1, low=0 (true)
*     * . . . . . . .  Busy ......... (pin 11), high=0, low=1 (inverted)
*
*   Control Register (base + 2) ..... outputs
*
*     7 6 5 4 3 2 1 0
*     . . . . . . . *  Strobe ....... (pin 1),  1=low, 0=high (inverted)
*     . . . . . . * .  Auto Feed .... (pin 14), 1=low, 0=high (inverted)
*     . . . . . * . .  Initialize ... (pin 16), 1=high, 0=low (true)
*     . . . . * . . .  Select ....... (pin 17), 1=low, 0=high (inverted)
*     * * * * . . . .  Unused
*
* Pins 18-25 are ground.  You can get fancy, and do some bidirectional transfers with certain
* parallel ports, but this simple structure works for everything I've tried it on.  For more
* information, consult some of the excellent FAQs on the Internet ...
*
* This module maintains shadow buffers for the data and control registers, so that a single
* bit can be changed without disturbing other bits within the same register.  All inputs and
* outputs have a corresponding function to read or write them, using the "official" signal name.
* In addition, the PrnIO_Data() function allows you to write to the entire data register at once,
* which is useful for communicating with byte-wide devices.
*
* The header file provides a number of macros which allow you to refer to the inputs and outputs
* by number, (e.g. PrnIO_In0(), PrnIO_Out0(), etc.).
*
* This module was written for use with Borland C/C++ v3.1.  It may be used with other compilers,
* but you'll most likely need to change the inport() and outport() functions to the equivalent
* library functions provided by the other compilers.  You may also need to change the names of the
* header files for other compilers ...
*
*********************************************************************************************************
*/


/*
*********************************************************************************************************
* Include Header Files
*********************************************************************************************************
*/
#include 
#include 
#include 
#include 
#include "prn_io.h"


/*
*********************************************************************************************************
* Constants
*********************************************************************************************************
*/
#define BASE_ADDRESS      0x0378                      // printer port base address
#define DATA_REGISTER     (BASE_ADDRESS+0)            //  address of data register
#define STATUS_REGISTER   (BASE_ADDRESS+1)            //  address of status register
#define CONTROL_REGISTER  (BASE_ADDRESS+2)            //  address of control register


/*
*********************************************************************************************************
* Private Data
*********************************************************************************************************
*/
static unsigned char data_reg;
static unsigned char control_reg;



// ...................................... Public Functions ..............................................


/*
*********************************************************************************************************
* PrnIO_Init()
*
* Description: Initialize module; must be called before any other functions in this module.
* Arguments  : none
* Returns    : none
*********************************************************************************************************
*/
void PrnIO_Init (void)
{
  data_reg = control_reg = 0;                         // clear shadow registers
}


/*
*********************************************************************************************************
* PrnIO_...()
*
* Description: Input and output routines.  These use the actual names of the pins.
*********************************************************************************************************
*/
void PrnIO_D0 (char state)
{
  if (state == 0)
    data_reg &= ~0x01;
  else
    data_reg |=  0x01;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_D1 (char state)
{
  if (state == 0)
    data_reg &= ~0x02;
  else
    data_reg |=  0x02;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_D2 (char state)
{
  if (state == 0)
    data_reg &= ~0x04;
  else
    data_reg |=  0x04;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_D3 (char state)
{
  if (state == 0)
    data_reg &= ~0x08;
  else
    data_reg |=  0x08;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_D4 (char state)
{
  if (state == 0)
    data_reg &= ~0x10;
  else
    data_reg |=  0x10;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_D5 (char state)
{
  if (state == 0)
    data_reg &= ~0x20;
  else
    data_reg |=  0x20;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_D6 (char state)
{
  if (state == 0)
    data_reg &= ~0x40;
  else
    data_reg |=  0x40;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_D7 (char state)
{
  if (state == 0)
    data_reg &= ~0x80;
  else
    data_reg |=  0x80;
  outport(DATA_REGISTER,data_reg);
}


void PrnIO_Data (unsigned char dataout)
{
  data_reg = dataout;
  outport(DATA_REGISTER,data_reg);
}


char PrnIO_Error (void)
{
  if (inport(STATUS_REGISTER) & 0x08)
    return 1;
  else
    return 0;
}


char PrnIO_Selected (void)
{
  if (inport(STATUS_REGISTER) & 0x10)
    return 1;
  else
    return 0;
}


char PrnIO_PaperOut (void)
{
  if (inport(STATUS_REGISTER) & 0x20)
    return 1;
  else
    return 0;
}


char PrnIO_Acknowledge (void)
{
  if (inport(STATUS_REGISTER) & 0x40)
    return 1;
  else
    return 0;
}


char PrnIO_Busy (void)
{
  if (inport(STATUS_REGISTER) & 0x80)
    return 0;
  else
    return 1;
}


void PrnIO_DataStrobe (char state)
{
  if (state == 0)
    control_reg |=  0x01;
  else
    control_reg &= ~0x01;
  outport(CONTROL_REGISTER,control_reg);
}


void PrnIO_Autofeed (char state)
{
  if (state == 0)
    control_reg |=  0x02;
  else
    control_reg &= ~0x02;
  outport(CONTROL_REGISTER,control_reg);
}


void PrnIO_InitOut (char state)
{
  if (state == 0)
    control_reg &= ~0x04;
  else
    control_reg |=  0x04;
  outport(CONTROL_REGISTER,control_reg);
}


void PrnIO_Select (char state)
{
  if (state == 0)
    control_reg |=  0x08;
  else
    control_reg &= ~0x08;
  outport(CONTROL_REGISTER,control_reg);
}

PRN_IO.H


/*
*********************************************************************************************************
* Module     : PRN_IO.H
* Author     : Randy Rasa
* Description: Header file for PRN_IO.C (Printer Port I/O Routines)
*********************************************************************************************************
*/


/*
*********************************************************************************************************
* Public Function Prototypes
*********************************************************************************************************
*/
void PrnIO_Init (void);
void PrnIO_D0 (char state);
void PrnIO_D1 (char state);
void PrnIO_D2 (char state);
void PrnIO_D3 (char state);
void PrnIO_D4 (char state);
void PrnIO_D5 (char state);
void PrnIO_D6 (char state);
void PrnIO_D7 (char state);
void PrnIO_Data (unsigned char dataout);
char PrnIO_Error (void);
char PrnIO_Selected (void);
char PrnIO_PaperOut (void);
char PrnIO_Acknowledge (void);
char PrnIO_Busy (void);
void PrnIO_DataStrobe (char state);
void PrnIO_Autofeed (char state);
void PrnIO_InitOut (char state);
void PrnIO_Select (char state);


/*
*********************************************************************************************************
* Macros
*********************************************************************************************************
*/
#define PrnIO_In0()     PrnIO_Error()
#define PrnIO_In1()     PrnIO_Selected()
#define PrnIO_In2()     PrnIO_PaperOut()
#define PrnIO_In3()     PrnIO_Acknowledge()
#define PrnIO_In4()     PrnIO_Busy()

#define PrnIO_Out0(x)   PrnIO_D0(x)
#define PrnIO_Out1(x)   PrnIO_D1(x)
#define PrnIO_Out2(x)   PrnIO_D2(x)
#define PrnIO_Out3(x)   PrnIO_D3(x)
#define PrnIO_Out4(x)   PrnIO_D4(x)
#define PrnIO_Out5(x)   PrnIO_D5(x)
#define PrnIO_Out6(x)   PrnIO_D6(x)
#define PrnIO_Out7(x)   PrnIO_D7(x)
#define PrnIO_Out8(x)   PrnIO_DataStrobe(x)
#define PrnIO_Out9(x)   PrnIO_Autofeed(x)
#define PrnIO_Out10(x)  PrnIO_InitOut(x)
#define PrnIO_Out11(x)  PrnIO_Select(x)

This source code is provided as-is, with no warranties or guarantees.


blog comments powered by Disqus