/****************************************************************************\
**																			**
\****************************************************************************/
#include <proto/exec.h>
#include <proto/misc.h>
#include <devices/timer.h>
#include <resources/misc.h>
#include <hardware/cia.h>
#include "lcd.h"
#define MINDELAY	80			/* delay for device to complete request */

struct Library *MiscBase=NULL;
extern struct timerequest *timereq;
extern struct CIA ciaa,ciab;
extern char *startup;		/*	if non-NULL, points to startup options	*/
BOOL portopen=FALSE,bitsopen=FALSE;

/****************************************************************************\
**	Allocate everything needed for port access								**
**																			**
**	Return 0 for success.													**
\****************************************************************************/
long lcd_alloc(struct lcdparams *param){
	BOOL success=TRUE;
	if(!(MiscBase=OpenResource("misc.resource"))) success=FALSE;
	if(!(portopen=(BOOL)!AllocMiscResource(MR_PARALLELPORT,"pario"))) success=FALSE;
	if(!(bitsopen=(BOOL)!AllocMiscResource(MR_PARALLELBITS,"pario"))) success=FALSE;
	if(success){
		ciaa.ciaprb=(UBYTE)0x00;
		ciaa.ciaddrb=(UBYTE)0xff;		/*	Put data lines as output		*/
		ciab.ciapra&=~(UBYTE)0x03;
		ciab.ciaddra|=(UBYTE)0x03;		/*	Put control lines as output		*/
	}
	return(success);
}

/****************************************************************************\
**	Free everything allocated.												**
**																			**
**	lcd_free() is called even when lcd_alloc() failed, to allow for			**
**	freeing the successful allocations in lcd_alloc()						**
\****************************************************************************/
void lcd_free(void){
	if(portopen) FreeMiscResource(MR_PARALLELPORT);
	if(bitsopen) FreeMiscResource(MR_PARALLELBITS);
}

/****************************************************************************\
**	AmigaDOS Delay(), but using microseconds								**
\****************************************************************************/
void lcd_delayfor(int micros){
	timereq->tr_node.io_Command=TR_ADDREQUEST;
	timereq->tr_time.tv_micro=micros%1000000;
	timereq->tr_time.tv_secs=micros/1000000;
	DoIO((struct IORequest *)timereq);	
}

/****************************************************************************\
**	Send code to LCD, with pause for LCD to comply							**
**																			**
**	Hardware:																**
**																			**
**	Centronics			LCD													**
**	D0...D7		->		d0...d7												**
**	BUSY		->		Enable												**
**	POUT		->		Register Select										**
**																			**
\****************************************************************************/
void lcd_putchar(UBYTE code,BOOL data,long micros){
	if(micros<MINDELAY) micros=MINDELAY;
	ciaa.ciaddrb=0xff;					/*	Parallel lines as output		*/
	ciaa.ciaprb=code;					/*	Put code on parallel data lines	*/
	if(!data){
		ciab.ciapra&=~((UBYTE)0x02);	/*	Data=0	->	RS=1				*/
	} else {
		ciab.ciapra|=(UBYTE)0x02;		/*	Data=1	->	RS=1				*/
	}

	lcd_delayfor(1);
	ciab.ciapra|=(UBYTE)0x01;			/*	Assert E line					*/
	lcd_delayfor(1);

	ciab.ciapra&=~((UBYTE)0x01);		/*	Disable E after 1000 ns			*/
	
	lcd_delayfor(micros);				/*	Wait while LCD processes...		*/

	ciaa.ciaddrb=0x00;					/*	float D0-D7 again (saves power)	*/
}
