/******
 *
 *	L E D . C                    by Jan Ceuleers, the Experimenter Board, 1993
 *	                                           part of the ISDN FOSSIL project
 *
 *	This module implements a data-driven visual state monitor. The intent is
 *	to connect a number of LEDs to a parallel printer port and make each of
 *	these LEDs correspond with a certain state or event.
 *
 *	The identifier ENABLE_LED must be #defined (in fos_isdn.h) for this
 *	functionality to be enabled. Keep in mind that performance will noticeably
 *	be affected by turning the LED monitor on; it's therefore only intended as
 *	an aid in debugging.
 *
 ******/

#define LED

#include "fos_isdn.h"

#ifdef ENABLE_LED

unsigned char bitmask[8] =
{
	'\x01', '\x02', '\x04', '\x08', '\x10', '\x20', '\x40', '\x80'
};

void ledOn(port_t *pport, unsigned trigger)
{
	unsigned port = P(led.portNumber);
	unsigned char mask;
	unsigned count;

	for (count = 0, mask = bitmask[0];
	     (count < 8);
	     count++, mask = bitmask[count])
	{
		if (P(led.trigger[count]) == trigger)
		{
			_asm
			{
				mov  dx,port
				in   al,dx
				or   al,mask
				out  dx,al
			}

			break;
		}
	}
}

void ledOff(port_t *pport, unsigned trigger)
{
	unsigned port = P(led.portNumber);
	unsigned char mask;
	unsigned count;

	for (count = 0, mask = ~bitmask[0];
	     (count < 8);
	     count++, mask = ~bitmask[count])
	{
		if (P(led.trigger[count]) == trigger)
		{
			_asm
			{
				mov  dx,port
				in   al,dx
				and  al,mask
				out  dx,al
			}

			break;
		}
	}
}

void ledInvert(port_t *pport, unsigned trigger)
{
	unsigned port = P(led.portNumber);
	unsigned char mask;
	unsigned count;

	for (count = 0, mask = bitmask[0];
	     (count < 8);
	     count++, mask = bitmask[count])
	{
		if (P(led.trigger[count]) == trigger)
		{
			_asm
			{
				mov  dx,port
				in   al,dx
				xor  al,mask
				out  dx,al
			}

			break;
		}
	}
}

void initializeLed(port_t *pport)
{
	switch(pport - ports)
	{
		case 0:
			P(led.portNumber) = 0x03bc;

			// FOSSIL state
/*			P(led.trigger)[0] = LT_STAT_RDA;
			P(led.trigger)[1] = LT_STAT_THRE;
			P(led.trigger)[2] = LT_STAT_TSRE;
			P(led.trigger)[3] = LT_STAT_DCD;
			P(led.trigger)[4] = LT_STAT_OVRN;
			P(led.trigger)[5] = 0;
			P(led.trigger)[6] = LT_ISDNDRIVER;
			P(led.trigger)[7] = LT_ISDNERROR;
*/
			// Buffer manipulation and background activity
/*			P(led.trigger)[0] = LT_TRANSMITCHAR;
			P(led.trigger)[1] = LT_RECVCHARWITHWAIT;
			P(led.trigger)[2] = LT_REQUESTSTATUS;
			P(led.trigger)[3] = LT_BLOCKFROMTXBUFND;
			P(led.trigger)[4] = LT_READBLOCK;
			P(led.trigger)[5] = LT_WRITEBLOCK;
			P(led.trigger)[6] = LT_POLLISDNDRIVER;
			P(led.trigger)[7] = LT_ISDNDRIVER;
*/
			// Call handling
/*			P(led.trigger)[0] = LT_CHECKCALLSTATE;
			P(led.trigger)[1] = LT_CHECKINCOMINGDATA;
			P(led.trigger)[2] = LT_CHECKOUTGOINGDATA;
			P(led.trigger)[3] = LT_REQUESTSTATUS;
			P(led.trigger)[4] = LT_ID_PENDING;
			P(led.trigger)[5] = LT_ID_STRINGRECVD;
			P(led.trigger)[6] = LT_TRANSMITLOOP;
			P(led.trigger)[7] = LT_ISDNDRIVER;
*/
			// Intense receive monitoring
			P(led.trigger)[0] = LT_CHARFROMRXBUF;
			P(led.trigger)[1] = LT_BLOCKFROMRXBUF;
			P(led.trigger)[2] = 0;
			P(led.trigger)[3] = LT_INFOABOUTDRIVER;
			P(led.trigger)[4] = LT_READBLOCK;
			P(led.trigger)[5] = LT_NDREADAHEAD;
			P(led.trigger)[6] = LT_STAT_RDA;
			P(led.trigger)[7] = LT_RECVCHARWITHWAIT;

			_asm mov dx,0x3bc
			_asm mov al,0
			_asm out dx,al
			break;

		case 1:
			// If you have 2 parallel ports, this address could point to
			// the second-one. Remember to disconnect the printer :-)
			P(led.portNumber) = 0x03bc;

			P(led.trigger)[0] = 
			P(led.trigger)[1] = 
			P(led.trigger)[2] = 
			P(led.trigger)[3] = 
			P(led.trigger)[4] = 
			P(led.trigger)[5] = 
			P(led.trigger)[6] = 
			P(led.trigger)[7] = 0;

			_asm mov dx,0x3bc
			_asm mov al,0
			_asm out dx,al
			break;
	}
}

#else
void initializeLed(port_t *pport) {};
#endif
