// ========================================================================
// Datei:  LP_FUNC.CPP
// Inhalt: Funktionen zur Ein- und Ausgabe mit der
//	   parallelen Schnittstelle.
//	   Es koennen 8 Bits ausgegeben werden (Data-Register) und
//	   5 Bits eingegeben werden.
//	   Die Funktionen geben nichts am Bildschirm aus und koennen
//	   daher universell verwendet werden. Falls ein Fehler auf-
//	   getreten ist, kann dies anhand der Rueckgabewerte festge-
//	   stellt werden.
//
// Autor:  Gerhard Juengling, HTL Wien 4, Sommer 2000
// ========================================================================

#include <conio.h>
#include "lp_func.h"

#define LPT1_BASE 0x378		//EA-Basisadressen
#define LPT2_BASE 0x278
#define LP_DATA lp_base+0	//Datenregister (Ausgaenge Bits 0..7)
#define LP_STAT lp_base+1       //Statusregister (Eingaenge Bits 3..7)
#define LP_CONT lp_base+2
#define LP_INPMASK 0xf8
#define LP_INVERT 0x78		//Maske zum Invertieren der Eingangsbits
				//damit beim Druecken der Tasten der
				//Eingang = 1 ist
unsigned char lp_outbits;
unsigned char lp_inbits;
unsigned char lp_initialized =FALSE;	//Flag gibt an, ob lp_func schon initialisiert wurde
unsigned int lp_base=LPT1_BASE;
int lp_stat=-4;


// ========================================================================
// lp_init: Initialisiert die Ein-Ausgaberoutinen und alle Variablen.
// Diese Funktion muss aufgerufen werden, da sonst alle anderen Funk-
// tionen eine Fehlermeldung zurueckgeben!
// Aufrufparameter:
//   int lptport: 1,2 oder 3 steht fuer LPT1, LPT2 oder LPT3
// Rueckgabewert (int): 0  kein Fehler
//			-1 keine parallele Schnittstelle vorhanden *)
//			-2 lp_init wurde schon aufgerufen
//			-3 gewuenschte Schnittstelle nicht vorhanden *)
// ========================================================================

int lp_init(int lptport)
{
	if (lp_initialized) {
	    lp_stat = -2;
	}
	else {
	    switch(lptport) {
	    case 1: lp_base = LPT1_BASE;
		    lp_initialized = TRUE;
		    lp_stat = 0;
		    break;
	    case 2: lp_base = LPT2_BASE;
		    lp_initialized = TRUE;
		    lp_stat = 0;
		    break;
	    default:lp_stat = -3;
		    break;
	    }
	}
	return (lp_stat);

}
// ========================================================================
// lp_info, lp_version: Informationen ueber die LP_FUNC Bibliothek
// Rueckgabewert (char *): Zeiger auf einen Infostring
// ========================================================================
char *lp_info()
{
    return("LP_FUNC: Funktionen zum Steuern der parallelen Schnittstelle G.Juengling 2000");
}
char *lp_version()
{
    return("LP_FUNC Version 1.0, Juni 2000");
}

// ========================================================================
// lp_errmsg: Initialisiert die Ein-Ausgaberoutinen und alle Variablen.
// Diese Funktion muss aufgerufen werden, da sonst alle anderen Funk-
// tionen eine Fehlermeldung zurueckgeben!
// Aufrufparameter:
//   int status: Status des letzten Funktionsaufrufes
// Rueckgabewert (char *): Zeiger auf eine Fehlermeldung
// ========================================================================

char *lp_errmsg(int status)
{
    switch (status) {
    case  0: return ("No Error");
    case -1: return ("No parallel Port found");
    case -2: return ("lp_init already executed");
    case -3: return ("Selected Port not found");
    case -4: return ("lp_init not yet executed");
    case -5: return ("Wrong Bit Number selected");
    case -6: return ("Bit value must be 0 or 1");
    default: return ("Unknown Error");
    }
}

// ========================================================================
// lp_output: Gibt 8 Datenbits an der gewaehlten parallelen Schnitt-
// stelle aus.
// Aufrufparameter:
//   unsigned char outbyte: Auszugebendes Bitmuster
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lp_output(unsigned char outbyte)
{
	lp_stat = 0;
	if (!lp_initialized) lp_stat = -4;
	else {
	   lp_outbits = outbyte;
	   outp(LP_DATA,lp_outbits);
	}
	return (lp_stat);
}
// ========================================================================
// lp_outbit: Setzt oder loescht eines der 8 Datenbits
// Aufrufparameter:
//   unsigned char bit_num: Nummer des auszugebenden Bits (0..7)
//   unsigned char value:   Wert des Bits (0,1)
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lp_outbit(unsigned char bit_num, unsigned char value)
{
	lp_stat = 0;
	if (!lp_initialized) lp_stat = -4;
	else if (bit_num > 7) lp_stat = -5;
	else if (value == 1) {
	   lp_outbits = lp_outbits | (1<<bit_num);
	   outp(LP_DATA,lp_outbits);
	}
	else if (value == 0) {
	   lp_outbits = lp_outbits & (0xFF-(1<<bit_num));
	   outp(LP_DATA,lp_outbits);
	}
	else lp_stat =-6;

	return (lp_stat);
}

// ========================================================================
// lp_input0: Liest 5 Datenbits (Bit 3..7) von der parallelen Schnittstelle
//   und legt sie unveraendert in der Variablen inbyte ab. Bei gedrueckter
//   Taste sind die entsprechenden Bits 0, Bit 7 ist invertiert.
// Aufrufparameter:
//   unsigned char &inbyte: Container fuer einzulesendes Bitmuster
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lp_input0(unsigned char &inbyte)
{
	lp_stat=0;
	if (!lp_initialized) lp_stat = -4;
	else {
	    lp_inbits = inp(LP_STAT);
	    inbyte = lp_inbits;
	}
	return (lp_stat);
}
// ========================================================================
// lp_input: Liest 5 Datenbits von der parallelen Schnittstelle und wandelt
//   sie derart um, dass die Bits 0..5 bei gedrueckter Taste 1 sind.
// Aufrufparameter:
//   unsigned char &inbyte: Container fuer einzulesendes Bitmuster
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lp_input(unsigned char &inbyte)
{
    int retval;
    retval = lp_input0(inbyte);
    inbyte = ((inbyte ^ LP_INVERT) & LP_INPMASK) >>3;
    return(retval);
}


// ========================================================================
// lp_status: Gibt den Errorcode der letzten lp_Funktion zurueck
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lp_status()
{
	return (lp_stat);
}
