//*** TDLPortIO: DriverLINX Port IO Driver wrapper component *****************
//**                                                                        **
//** File: TDLPortIO.cpp                                                    **
//**                                                                        **
//** Copyright (c) 1999 John Pappas (DiskDude). All rights reserved.        **
//**     This software is FreeWare.                                         **
//**                                                                        **
//**     Please notify me if you make any changes to this file.             **
//**     Email: diskdude@poboxes.com                                        **
//**                                                                        **
//**                                                                        **
//** The following resources helped in developing the install, start, stop  **
//** and remove code for dynamically opening/closing the DriverLINX WinNT   **
//** kernel mode driver.                                                    **
//**                                                                        **
//**   "Dynamically Loading Drivers in Windows NT" by Paula Tomlinson       **
//**   from "Windows Developer's Journal", Volume 6, Issue 5. (C code)      **
//**      ftp://ftp.mfi.com/pub/windev/1995/may95.zip                       **
//**                                                                        **
//**   "Hardware I/O Port Programming with Delphi and NT" by Graham Wideman **
//**      http://www.wideman-one.com/tech/Delphi/IOPM/index.htm             **
//**                                                                        **
//**                                                                        **
//** Special thanks to Peter Holm <comtext3@post4.tele.dk> for his          **
//** algorithm and code for detecting the number and addresses of the       **
//** installed printer ports, on which the detection code below is based.   **
//**                                                                        **
//** this Version add support for Win2000 and XP                            **
//** Modified 07.12.03 DJMSoftware                                          **
//**                                                                        **
//**                                                                        **
//**                                                                        **
//*** http://diskdude.cjb.net/ ***********************************************
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include "DLPrinterPortIO.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
//  ValidCtrCheck est utilisé pour vérifier que les composants créés n'ont
// aucune fonction virtuelle pure.
//

static inline void ValidCtrCheck(TDLPrinterPortIO *)
{
        new TDLPrinterPortIO(NULL);
}
//---------------------------------------------------------------------------
__fastcall TDLPrinterPortIO::TDLPrinterPortIO(TComponent* Owner)
        : TComponent(Owner)
{
   // Detect the printer ports available
   mDriver.DetectPorts();
     // Set the default LPT number
   SetLPTNumber(1);
}
//---------------------------------------------------------------------------
namespace Dlprinterportio
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TDLPrinterPortIO)};
                 RegisterComponents("DiskDude", classes, 0);
        }
}
//---------------------------------------------------------------------------
void __fastcall TDLPrinterPortIO::SetLPTNumber(char Number)
{
   // Note that we don't make sure it is within the range 1..FLPTCount
   // because there _might_ (can someone claify this?) be a port numbered
   // as #2, where it may be the _only_ port installed on the system.
   if (Number>0 && Number<MAX_LPT_PORTS)
   {
      mDriver.FLPTNumber=Number;
      mDriver.FLPTBase=mDriver.FLPTAddress[Number];
   }
}
//---------------------------------------------------------------------------
bool __fastcall TDLPrinterPortIO::GetPin(char index)
{
    switch (index)
   {
      case 1:  return (Port[mDriver.FLPTBase+2]&BIT0)==0; // Inverted
      case 2:  return (Port[mDriver.FLPTBase]&BIT0)!=0;
      case 3:  return (Port[mDriver.FLPTBase]&BIT1)!=0;
      case 4:  return (Port[mDriver.FLPTBase]&BIT2)!=0;
      case 5:  return (Port[mDriver.FLPTBase]&BIT3)!=0;
      case 6:  return (Port[mDriver.FLPTBase]&BIT4)!=0;
      case 7:  return (Port[mDriver.FLPTBase]&BIT5)!=0;
      case 8:  return (Port[mDriver.FLPTBase]&BIT6)!=0;
      case 9:  return (Port[mDriver.FLPTBase]&BIT7)!=0;
      case 10: return (Port[mDriver.FLPTBase+1]&BIT6)!=0;
      case 11: return (Port[mDriver.FLPTBase+1]&BIT7)==0; // Inverted
      case 12: return (Port[mDriver.FLPTBase+1]&BIT5)!=0;
      case 13: return (Port[mDriver.FLPTBase+1]&BIT4)!=0;
      case 14: return (Port[mDriver.FLPTBase+2]&BIT1)==0; // Inverted
      case 15: return (Port[mDriver.FLPTBase+1]&BIT3)!=0;
      case 16: return (Port[mDriver.FLPTBase+2]&BIT2)!=0;
      case 17: return (Port[mDriver.FLPTBase+2]&BIT3)==0; // Inverted
      default: return false; // pins 18-25 (GND), and other invalid pins
   }
}
//---------------------------------------------------------------------------

void __fastcall TDLPrinterPortIO::SetPin(char index, bool state)
{
     if (state)
      switch (index)
      {
         case 1:  Port[mDriver.FLPTBase+2]&=~BIT0; break; // Inverted
         case 2:  Port[mDriver.FLPTBase]|=BIT0;    break;
         case 3:  Port[mDriver.FLPTBase]|=BIT1;    break;
         case 4:  Port[mDriver.FLPTBase]|=BIT2;    break;
         case 5:  Port[mDriver.FLPTBase]|=BIT3;    break;
         case 6:  Port[mDriver.FLPTBase]|=BIT4;    break;
         case 7:  Port[mDriver.FLPTBase]|=BIT5;    break;
         case 8:  Port[mDriver.FLPTBase]|=BIT6;    break;
         case 9:  Port[mDriver.FLPTBase]|=BIT7;    break;
         /*
         case 10: Port[FLPTBase+1]|=BIT6;  break;
         case 11: Port[FLPTBase+1]&=~BIT7; break; // Inverted
         case 12: Port[FLPTBase+1]|=BIT5;  break;
         case 13: Port[FLPTBase+1]|=BIT4;  break;
         */
         case 14: Port[mDriver.FLPTBase+2]&=~BIT1; break; // Inverted
         /*
         case 15: Port[FLPTBase+1]|=BIT3;  break;
         */
         case 16: Port[mDriver.FLPTBase+2]|=BIT2;  break;
         case 17: Port[mDriver.FLPTBase+2]&=~BIT3; break; // Inverted
         default: break; // pins 18-25 (GND), and other invalid pins
      }
   else
      switch (index)
      {
         case 1:  Port[mDriver.FLPTBase+2]|=BIT0;   break; // Inverted
         case 2:  Port[mDriver.FLPTBase]&=~BIT0;    break;
         case 3:  Port[mDriver.FLPTBase]&=~BIT1;    break;
         case 4:  Port[mDriver.FLPTBase]&=~BIT2;    break;
         case 5:  Port[mDriver.FLPTBase]&=~BIT3;    break;
         case 6:  Port[mDriver.FLPTBase]&=~BIT4;    break;
         case 7:  Port[mDriver.FLPTBase]&=~BIT5;    break;
         case 8:  Port[mDriver.FLPTBase]&=~BIT6;    break;
         case 9:  Port[mDriver.FLPTBase]&=~BIT7;    break;
         /*
         case 10: Port[FLPTBase+1]&=~BIT6;  break;
         case 11: Port[FLPTBase+1]|=BIT7;   break; // Inverted
         case 12: Port[FLPTBase+1]&=~BIT5;  break;
         case 13: Port[FLPTBase+1]&=~BIT4;  break;
         */
         case 14: Port[mDriver.FLPTBase+2]|=BIT1;   break; // Inverted
         /*
         case 15: Port[FLPTBase+1]&=~BIT3;  break;
         */
         case 16: Port[mDriver.FLPTBase+2]&=~BIT2;  break;
         case 17: Port[mDriver.FLPTBase+2]|=BIT3;   break; // Inverted
         default: break; // pins 18-25 (GND), and other invalid pins
      }

}
//---------------------------------------------------------------------------
bool __fastcall TDLPrinterPortIO::LPTPrintChar(char CH)
{
        // Write data to Base+0
    Port[mDriver.FLPTBase]=(UCHAR)CH;
    // Write 0Dh to Base+2.
    Port[mDriver.FLPTBase+2]=0x0D;
    // Make sure there's a delay of at least one microsecond
    Sleep(1);
    // Write 0Ch to Base+2.
    Port[mDriver.FLPTBase+2]=0x0C;
    // Input from Base+1 and check if Bit 7 is 1.
    // Return this status as whether the character was printed
    return (Port[mDriver.FLPTBase+1]&BIT7)!=0;
}
//---------------------------------------------------------------------------


