/* vim: set sw=8 ts=8 si : */
/*********************************************
* Author: Guido Socher, Copyright: GPL 
* Clock frequency     : 4,000000 MHz
* Copyright: GPL
**********************************************/
#include 
#include 
#include 
#include 
#include "avr-util.h"
#include "lcd.h"
#include "uart.h"
#include "hardwarewd.h"

static volatile unsigned char wdtimer; 
static volatile unsigned char timedout; 


/* the following function will be called when the timer interrupt hits */
SIGNAL(SIG_OVERFLOW1) {
	wdtimer--;
	outp(0,TCNT1H); /* set internal interrup timer */
	outp(0,TCNT1L); /* set internal interrup timer */
	if (wdtimer==0){
		outp(0,TCCR1B); // stop timer
		lcd_clrscr();
		/* toggle the relai */
		timedout=1;
		sbi(WDPORT,WD); /* on */
		lcd_puts_P("WD reset...");
		/* wait */
		delay_ms(700);
		uart_reset();
		wdtimer=255;
		cbi(WDPORT,WD); /* off */
	}
}

/* return 1 on wd on, 0 otherwise */
unsigned char wd_status(void)
{
	if (inp(TCCR1B)){
		return(1);
	}else{
		if (timedout==1){
			return(2);
		}else{
			return(0);
		}
	}
}

void wd_settime(unsigned char timeout)
{
	wdtimer=timeout;
}

void wd_gettime(unsigned char *timeout)
{
	*timeout=wdtimer;
}

void wd_start(void)
{
	/* prescale = 4MHz/1024 */
	outp(5,TCCR1B);
	timedout=0;
}

void wd_stop(void)
{
	outp(0,TCCR1B);
	
}

/* init hardware watchdog. You must enable interrupt with
* sei() in the main program */
void wd_init(void)
{
	/* initialize WD/RELAI as output */
	sbi(WDDDR,WD);
	cbi(WDPORT,WD);
	wdtimer=255;
	timedout=0;
	sbi(TIMSK,TOIE1);
	/* write high byte first */
	outp(0x0,TCNT1H); /* set internal interrup timer */
	outp(0x0,TCNT1L); /* set internal interrup timer */
	/* write high byte first */
	outp(0xFF,OCR1H); /* set internal compare register */
	outp(0xFF,OCR1L); /* set internal compare register */
	outp(0,TCCR1A); /* timer mode */
	outp(0,TCCR1B); /* off */
}