/*                    Listing 1                     */
/*****************************************************
                Name: PAR_COMM.C
         Description: Library of functions to support
                      bidirection communications with
                      PC parallel port.
Global Function List: correct_bios_status
                      correct_port_status
                      get_prn_port
                      in_bios_nibble
                      in_bios_status
                      in_port_nibble
                      in_port_status
                      invert_bit
         Portability: MS-DOS Microsoft C or Borland C
*****************************************************/

/* Standard C */
#include <bios.h>
#include <conio.h>

/* Own */
#include <par_comm.h>
#if !defined ( FAR )
   #define FAR _far
#endif

/*****************************************************
       Name: correct_bios_status
 Parameters: Status - printer port status
     Return: Corrected printer port status
Description: Corrects the printer status that was
             obtained using the BIOS so it matches
             the actual line levels.
*****************************************************/
unsigned correct_bios_status( unsigned Status )
   {
   Status = invert_bit( Status, 7 );
   Status = invert_bit( Status, 6 );
   return ( Status );
   }

/*****************************************************
       Name: correct_bios_status
 Parameters: Status - printer port status
     Return: Corrected printer port status
Description: Corrects the printer status that was
             obtained directly from the port so it
             matches the actual line levels.
*****************************************************/
unsigned correct_port_status( unsigned Status )
   {
   Status = invert_bit( Status, 7 );
   Status = invert_bit( Status, 3 );
   return ( Status );
   }

/*****************************************************
       Name: get_prn_port
 Parameters: PrnNum - number of the printer device
             LPT1 - 0, LPT2 - 1, LPT3 - 2, LPT4 - 3
     Return: printer port number
Description: Retrives the printer port number from
             the PC's printer data table.
*****************************************************/
unsigned get_prn_port( unsigned PrnNum )
   {
   return ( *((unsigned FAR *)(( 0x40LU << 16 ) |
         ( 0x08U + 2 * PrnNum ))));
   }

/*****************************************************
       Name: in_bios_nibble
 Parameters: PrnPort - address of printer port
     Return: Nibble read in from printer port
Description: Inputs a nibble from a printer port using
             a call to the PC's BIOS.  The
             status lines are read and corrected.  The
             high nibble of the status lines is stored
             in the low nibble of the return value.
             Bit 3 of the status is used to set the
             sign bit of the return value.
*****************************************************/
unsigned in_bios_nibble( unsigned PrnNum )
   {
   unsigned Nibble;

   Nibble = _bios_printer( _PRINTER_STATUS,
         PrnNum, 0 );
   Nibble = correct_bios_status( Nibble );
   Nibble = ( Nibble << ( sizeof( unsigned ) * 8 - 4
         )) | ( Nibble >> 4 );
   return ( Nibble );
   }

/*****************************************************
       Name: in_bios_status
 Parameters: PrnNum - number of the printer device
             LPT1 - 0, LPT2 - 1, LPT3 - 2, LPT4 - 3
     Return: printer status bits in low byte
Description: Gets the status byte from a printer port
             using the BIOS.
*****************************************************/
unsigned in_bios_status( unsigned PrnNum )
   {
   return ( _bios_printer( _PRINTER_STATUS,
         PrnNum, 0 ));
   }

/*****************************************************
       Name: in_port_nibble
 Parameters: PrnPort - address of printer port
     Return: Nibble read in from printer port
Description: Inputs a nibble from a printer port
             with a direct read from the port.  The
             status lines are read and corrected.  The
             high nibble of the status lines is stored
             in the low nibble of the return value.
             Bit 3 of the status is used to set the
             sign bit of the return value.
*****************************************************/
unsigned in_port_nibble( unsigned PrnPort )
   {
   unsigned Nibble;

   Nibble = in_port_status( PrnPort );
   Nibble = correct_port_status( Nibble );
   Nibble = ( Nibble << ( sizeof( unsigned ) * 8 - 4
         )) | ( Nibble >> 4 );
   return ( Nibble );
   }

/*****************************************************
       Name: in_port_status
 Parameters: PrnPort - printer port number
     Return: printer status bits in low byte
Description: Gets the status byte from a printer port
             and masks off the lower three bits.
*****************************************************/
unsigned in_port_status( unsigned PrnPort )
   {
   return ( 504 /* 11111000 */ & inp( PrnPort + 1 ));
   }

/*****************************************************
       Name: invert_bit
 Parameters: Val - value to invert a single bit in
             Bit - number of bit in Val to invert
     Return: Val with Bit inverted
Description: Inverts a single designated bit in Val.
*****************************************************/
unsigned invert_bit( unsigned Val, unsigned Bit )
   {
   return (( Val & ~( 1U << Bit )) |
         (( !(( Val >> Bit ) & 1U )) << Bit ));
   }

/* End of File */
