// Parallellports-klass av PEK '2000
// För att sända och ta emot signaler med parallellporten
// pek@3base.net


#ifndef __peks_parport_routines__
#define __peks_parport_routines__


#include <conio.h>
#include <dos.h>


// Status bitar
#define S_IRQ 0x04
#define S_ERROR 0x08
#define S_SLCT 0x10
#define S_PE 0x20
#define S_ACK 0x40
#define S_BUSY 0x80

// Control bitar
#define C_STROBE 0x01
#define C_AUTOFD 0x02
#define C_INIT 0x04
#define C_SLCTIN 0x08
#define C_IRQENABLE 0x10
#define C_DIRECTION 0x20

#define DATAP 0
#define STATUSP 1
#define CONTROLP 2

// Input el. Output hos Direction biten
#define D_OUTPUT 0
#define D_INPUT 1


class _parport
{
	private:
	unsigned int lpt_base;

	public:
	_parport(int port);
	~_parport(void);
	void Set_Data(unsigned char data);
	void Set_Control(unsigned char data);
	unsigned char Get_Status(void);
	unsigned char Get_Data(void);
	unsigned char Get_Control(void);
	unsigned int Get_Adr(int port);
   void Set_Direction(int directn);
	void Change_Port(int port);
};


// --------------------------------------------------------


_parport::_parport(int port)
{
	Change_Port(port);
}


_parport::~_parport(void)
{

}


// För att sända data på portens data-pinnar D0-D7.
// Input : en byte data som ska sändas
// Output : inget
void _parport::Set_Data(unsigned char data)
{
	outp(lpt_base+DATAP, data);
}


// För att sätta controll-bitarna, se upp med Direction-biten
// Input : en byte data som ska sändas
// Output : inget
void _parport::Set_Control(unsigned char data)
{
	outp(lpt_base+CONTROLP, data);
}


// Hämta portens status-bitar
// Input : inget
// Output : en byte med status-bitarna
unsigned char _parport::Get_Status(void)
{
	return inp(lpt_base+STATUSP);
}


// Hämta vad som finns skrivit på data-pinnarna, ligger på data-pinnarna
// Input : inget
// Output : en byte med data-bitarna
unsigned char _parport::Get_Data(void)
{
	return inp(lpt_base+DATAP);
}


// Hämta vilka control-bitar som är satta
// Input : inget
// Output : en byte med control-bitarna
unsigned char _parport::Get_Control(void)
{
	return inp(lpt_base+CONTROLP);
}


// Få reda på en LPT-ports adress
// Input : LPT-port (1-4)
// Output : Portens adress, 16 bitar
unsigned int _parport::Get_Adr(int port)
{
	unsigned int far *ptradr;

	if(port >= 1 && port <= 4)
	{
		ptradr = (unsigned int far *) MK_FP(0x0040, 0x0008);
		ptradr += (port-1);
		return *ptradr;
	}
	else return 0;
}


// Sätter data-pinnarna som Input eller Output
// Input : D_INPUT el. D_OUTPUT (1 el. 0)
// Output : inget
void _parport::Set_Direction(int directn)
{
	if(directn == D_OUTPUT)
		outp(lpt_base+CONTROLP, Get_Control() & (0xFF-C_DIRECTION));
	else if(directn == D_INPUT)
		outp(lpt_base+CONTROLP, Get_Control() | C_DIRECTION);
}


// Ändrar vilken parallell-port som ska användas
// Input : LPT-port (1-4)
// Output : inget
void _parport::Change_Port(int port)
{
	lpt_base = Get_Adr(port);
}

#endif
