/**************************************************************/
/* Hardware Function Library                                  */
/*                                                            */
/*                                  ver 1.0  Oct. 15 1996     */
/*                                      1.1  Nov. 24 1996     */
/*                                      1.2  Dec. 15 1996     */
/*                                                            */
/*                                    developed by N.Hayashi  */
/**************************************************************/ 

#include"iodef.h"
#include"hard.h"

int pit1=0;
void pit1_clk_init();

void pit1_clk_init()
{
	outportb(TCR1,0x00);		/* clear TCR1  */
	outportl(CPR1,0x000001);	/* TOUT 125kHz */
					/* 0x01 = (1/125kHz)/2 /(1/8MHz)/32 prescaler */
	outportb(TCR1,0x41);		/* square wave */
}


/* Infrared sensor functions */

void irs_init()
{
	if(pit1!=1)
	{
		pit1_clk_init();
		pit1=1;
	}
	outportb(PGCR2,0x08);		/* clear PGCR2 */
	outportb(PSRR2,0x1c);
	outportb(PBCR2,0xA0);		/* submode 1x  */
	outportb(PBDDR2,0x00);		/* all input   */
	outportb(PBCR2,0xAA);		/* submode 00 , int enable   */
	outportb(PIVR2,72+2 );		/* infrared ray sensor interrupt causes by H3 */
	irs_disable_int();
}

void irs_disable_int()
{
	outportb(PSR2,0x04);		/* clear H3S   */
	outportb(PBCR2,0xA0);		/* submode 00 , int disable */
}

void irs_enable_int()
{
	outportb(PBCR2,0xAA);		/* submode 00 , int enable */
}

int irs_data()
{
	return(inportb(PBDR2)&0xff);
}


/* Rotary encoder and Touch sensor functions */

void re_ts_init()
{
	re_counter_reset();
}

void re_counter_reset()
{
	outportb(CRST,0x03);		/* counter reset */
}

int ts_data()
{
	return((inportb(EDRH)&0xf0)/16);
}

RE_TS_DATA re_ts_data()
{
	int _data_rl,_data_rh,_data_ll,_data_lh;
	RE_TS_DATA _data;

	_data_rl = inportb(EDRL) & 0xff;/* read count data */
	_data_rh = inportb(EDRH) ;
	_data_ll = inportb(EDLL) & 0xff;
	_data_lh = inportb(EDLH) & 0x0f;
	re_counter_reset();
	_data.ts =( _data_rh & 0x70)/16;
	_data_rh = _data_rh & 0x0f;
	_data.r  = ( _data_rh << 8 ) + _data_rl;
	if ((_data.r & 0x800) != 0) _data.r = (_data.r | 0xfffff000);
	_data.l  = ( _data_lh << 8 ) + _data_ll;
	if ((_data.l & 0x800) != 0) _data.l = (_data.l | 0xfffff000);
	return(_data);
}

void ts_enable_int()
{
	outportb(TSIE,0x01);		/* touch sensor interrupt enable */
	sys11(4);			/* IRQ4 enable */
}

void ts_disable_int()
{
	sys10(4);			/* IRQ4 disable */
	outportb(TSIE,0x00);		/* touch sensor interrupt disable */
}


/* Ultra sonic sensor functions */

void uss_init(_task)
int _task;
{
        outportb(PACR2,0x20);		/* submode 00 ,int disable */
        outportb(PADDR2,0x03);
        outportb(PGCR2,0x38);		/* mode 0 and H1,H3 enable */
	outportb(TCR2,0x00);		/* clear TCR2              */
	outportl(CPR2,USS_LIMIT);	/* count for us-wave to go & return 3 meter        */
	outportb(TCR2,0xb2);		/* device watchdog         */
	outportb(PIVR2,72+0);		/* uss interrupt caused by H1   */
	outportb(TIVR2,72+0);		/* uss interrupt caused by tout */
}

void uss_start(_sensor_ch)
int _sensor_ch;
{
	outportb(TCR2,0xb3);            /* Timer enable  */
	outportb(PADR2,_sensor_ch);	/* sensor select */
	outportb(PACR2,0x28);           /* H2 asert      */
	outportb(PACR2,0x22);           /* H2 negate and H1 interrupt enable */
}

void uss_stop()
{
	outportb(TCR2,0xb2);            /* Timer disable     */
	outportb(PACR2,0x20);           /* interrupt disable */
}

int uss_data()
{
	int _h,_m,_l;
	_h = inportb(CNTR2 +2) & 0xff;	/* read count data */
	_m = inportb(CNTR2 +4) & 0xff;
	_l = inportb(CNTR2 +6) & 0xff;
	return((USS_LIMIT - ( (_h<<16) + (_m<<8) +_l ) ) * 32/(double)80000 * 340 /2);
}

int uss_chk_int()			/* interrupt type check (under flow) */
{
	return(inportb(PSR2) & 0x01);
}

int uss_chk_conect()
{
	return((inportb(PADR2) & 0x04)>>2);
}


/* PWM functions */

#define DUTY_MAX (128-1)
#define CW        0
#define CCW       1
#define PWM_R     PADR1
#define PWM_L     PBDR1

void pwm_init()
{
	if (pit1 !=1)
	{
		pit1_clk_init();
		pit1 = 1;
	}
	outportb(PGCR1,0x00);		/*      clear PGCR1     */
	outportb(PSRR1,0x00);
	outportb(PACR1,0x80);		/*      submode 1x      */
	outportb(PADDR1,0xff);		/*      all output      */
	outportb(PBCR1,0x80);		/*      submode 1x      */
	outportb(PBDDR1,0xff);		/*      all output      */
	outportb(PGCR1,0x00);		/*      mode 0          */
}

void pwm_data(_duty_r,_duty_l)
int _duty_r,_duty_l;
{
	int _dir_r,_dir_l;
	if(_duty_r > 100)_duty_r=100;
	if(_duty_l > 100)_duty_l=100;
	if(_duty_r < -100)_duty_r=-100;
	if(_duty_l < -100)_duty_l=-100;
	
	_dir_r = _dir_l = CW;		/* set direction of rotation */ 
	if(_duty_r < 0)
	{
		_dir_r   = CCW;
		_duty_r *= -1;
	}
	if(_duty_l < 0)
	{
		_dir_l   = CCW;
		_duty_l *= -1;
	}
	outportb(PWM_R,(((_duty_r * DUTY_MAX / 100) << 1) + _dir_r));
	outportb(PWM_L,(((_duty_l * DUTY_MAX / 100) << 1) + _dir_l));
}


/* MMI functions */

int dipsw_data()
{
	return(inportb(PBDR0)&0xf);
}

int _led[LED_NO],_red,_green;

void mmi_init()
{
	outportb(PGCR0,0x00);		/*      clear PGCR0     */
	outportb(PSRR0,0x1e);
	outportb(PACR0,0xa0);		/*      submode 1x      */
	outportb(PADDR0,0xff);		/*      all output      */
	outportb(PBCR0,0x80);		/*      submode 1x      */
	outportb(PBDDR0,0x10);
	outportb(PGCR0,0x22);		/*      mode 0          */
	outportb(TCR0,0x00);		/*      clear TCR0      */
	outportl(CPR0,0x00003f);	/*      TOUT 2kHz       */
					/*      0x3f = (1/2000)/2 sec /(1/8MHz) /32 prescaler   */
	outportb(TCR0,0x41);		/*      square wave     */
	led_set(0,0);
	led_set(1,0);
	led_set(2,0);
	led_set(3,0);
	led_on(OFF);
}

void led_set(_led_no,_data)
int _led_no,_data;
{
	if(((_data >=0) && (_data <=9))&&((_led_no >=0) && (_led_no <= 3)))
	{
		_led[_led_no] = _data;
		outportb(PADR0,_green*0x80+_red*0x40+_led_no*0x10+_data);
		outportb(PACR0,0xa0);	/*making latch enable pulse*/
		outportb(PACR0,0xa8);
		outportb(PACR0,0xa0);
	}
}

void led_on(_data)
int _data;
{
	_green=_red=0;
	if((_data & GREEN)!=0)
	{
		_green=1;
	}
	if((_data & RED)!=0)
	{
		_red=1;
	}
}

void btn_disable_int()
{
	outportb(PBCR0, 0x80);
}

void btn_enable_int()
{
	outportb(PSR0, 0x08);
	outportb(PBCR0, 0x84);
}

int pow_chk()
{
	return((inportb(PBDR0)&0x40)>>6);
}